@vladjaj

Как сделать привязку в WPF MVVM к динамическому списку CheckBox?

Имеется 2 сущности EFcore
publuc class User 
{
    public int Id {get; set;}
    public string Name {get; set;}
    public List<Hobby> Hobbies {get; set;}
}

public class Hobby
{
    public int Id {get; set;}
    public string Name {get; set;}
}

Я получаю UserViewModel
public class UserViewModel
{
    DBContext db;
    public User User {get; set;}

    public class CheckBox
    {
        public int Id {get;set;}
        public string Name {get; set;}
        public bool IsChecked {get; set;}
    }

    public List<CheckBox> ListCheckBox;
    // команда обновляющая состояние User
    private ICommand _UpdateUserCommand;
    public ICommand UpdateUserCommand => _UpdateUserCommand ??=
            new BaseCommand(OnUpdateUserCommandExecuted, CanUpdateUserCommandExecute);
    private bool CanUpdateUserCommandExecute(object p) => db.ChangeTracker.HasChanges() ? true : false;
    private void OnUpdateUserCommandExecuted(object p)
    {
         db.SaveChanges();
    }

    UserViewModel(UserId)
    {
        User = db.Users.Include(h=>h.Hobbies).FirstOfDefault(u=u.Id == UserId);
        
        // получаю ListCheckBox для заполнения динамического списка CheckBox
        ListCheckBox = new List<CheckBox>();
            var Result = from hobby in db.Hobbies
                        select new CheckBox
                        {
                            Id = hobby.Id,
                            Name = hobby.NameFull,
                            IsChecked = User.Hobbies.Contains(hobby)
                        };
        ListCheckBox = Result.ToList();
    }
}
В окне WPF UserEdit я формирую динамический список
<ListBox ItemsSource="{Binding ListCheckBox}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <WrapPanel>
                <CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="Checked">
                            <i:InvokeCommandAction Command="{Binding ????????}" />
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </CheckBox>
            </WrapPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>


Дальше я зашел в тупик.
Если сделать команду, CheckBoxUpdate в классе User, то в окне UserEdit не получается привязать команду к элементу списка.
Если же эту команду размещать в классе CheckBox, то непонятно как обновлять состояние User.
public ICommand CheckBoxUpdate  
    private void OnCheckBoxUpdateCommandExecuted(CheckBox CurrentHobby)
    {
        if (CurrentHobby.Checked)
        {
            User.Hobbies.Add(CurrentHobby);
        }
        else
        {
            User.Hobbies.Remove(CurrentHobby);
        }
    }


Можно конечно обрабатывать событие как в Winform, но это противоречит MVVM
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}" 
                            Click="CheckBoxUpdate_Click">
                </CheckBox>


Подскажите в какую сторону копать дальше, или поделитесь ссылкой на работающий пример.
Мне кажется задача очень распространенная.
  • Вопрос задан
  • 198 просмотров
Пригласить эксперта
Ответы на вопрос 1
phoenixbk
@phoenixbk
Можно примерно так сделать:
public class HobbyCheckBoxItem
{
	private readonly User _user;

	public HobbyCheckBoxItem(User user, Hobby hobby)
	{
		_user = user;
		Hobby = hobby;
		_isChecked = user.Hobbies.Contains(hobby);
	}

	public Hobby Hobby { get; }

	private bool _isChecked;

	public bool IsChecked
	{
		get => _isChecked;
		set
		{
			if (_isChecked == value) return;
			_isChecked = value;
			if (value) _user.Hobbies.Add(Hobby);
			else _user.Hobbies.Remove(Hobby);
			// save db
		}
	}
}

И в биндинге CheckBox тогда будет не Content="{Binding Name}", а Content="{Binding Hobby.NameFull}"
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы