Флажки в DataTemplate ListBox Binding и триггеры с использованием MVVM - PullRequest
2 голосов
/ 15 марта 2020

Я изучаю, как использовать MVVM и как связывать данные в приложении WPF. Я создал собственный CheckedListBox в файле XAML следующим образом:

        <ListBox x:Name="materialsListBox" ItemsSource="{Binding CustomCheckBox}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <CheckBox IsChecked="{Binding Path=IsChecked, UpdateSourceTrigger=PropertyChanged, Mode=OneWayToSource}" Content="{Binding Item}" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

, а также хочу, чтобы одно изображение динамически отображалось для каждого проверяемого CheckBox. Я понимаю, что мне нужно использовать свойство Binding и UpdateSourceTrigger, но я не уверен, как это реализовать. Что я должен добавить здесь, чтобы мое приложение делало то, что я хочу?

        <Image HorizontalAlignment="Left" Height="100" Margin="432,146,0,0" VerticalAlignment="Top" Width="100"/>

Вот часть моего C# кода для ViewModel:

    public class MainViewModel : ViewModelBase
    {
        private ObservableCollection<CheckedListItem<string>> _customCheckBox;
        public ObservableCollection<CheckedListItem<string>> CustomCheckBox
        {
            set
            {
                _customCheckBox = value;
                OnPropertyChanged();
            }
            get { return _customCheckBox; }
        }

        public class CheckedListItem<T> : ViewModelBase
        {
            private bool _isChecked;
            private T _item;

            public CheckedListItem()
            {
            }

            public CheckedListItem(T item, bool isChecked = false)
            {
                item = _item;
                isChecked = _isChecked;
            }

            public T Item
            {
                set
                {
                    _item = value;
                    OnPropertyChanged();
                }
                get { return _item; }
            }


            public bool IsChecked
            {
                set
                {
                    _isChecked = value;
                    OnPropertyChanged();
                }
                get { return _isChecked; }
            }
        }
...

Спасибо за любую рекомендацию .

1 Ответ

1 голос
/ 29 марта 2020

Один простой способ сделать события ProperyChanged - использовать базовый набор для ViewModelBase this.Set, потому что он вызовет измененное событие для вас.

, чтобы сделать это, я разделил модель представления и просмотр на 2, один для основного вида и один для вида, сочетающего флажок и изображение. Вы можете сделать это с таким, как у вас, но мне было проще.

Просмотр модели для CheckBox и изображения

public class CheckBoxViewModel : ViewModelBase
{
    private bool isChecked;
    private string imageSource;
    private string imageName;

    public CheckBoxViewModel(string imageSource, string imageName)
    {
        this.ImageSource = imageSource;
        this.ImageName = imageName;

    }
    public ICommand Checked => new RelayCommand<string>(this.OnChecked);

    private void OnChecked(object imageName)
    {

    }
    public string ImageSource
    {
        get { return this.imageSource; }
        set { this.Set(() => this.ImageSource, ref this.imageSource, value); }
    }
    public string ImageName
    {
        get { return this.imageName; }
        set { this.Set(() => this.ImageName, ref this.imageName, value); }
    }

    public bool IsChecked
    {
        get { return this.isChecked; }
        set { this.Set(() => this.IsChecked, ref this.isChecked, value); }
    }
}

Главное окно Просмотр модели

public class MainViewModel : ViewModelBase
{
    private ObservableCollection<CheckBoxViewModel> items = new ObservableCollection<CheckBoxViewModel>();

    public ObservableCollection<CheckBoxViewModel> Items => this.items;
    public MainViewModel()
    {
        var view = new CheckBoxViewModel("Image.Jpg", "Image 1");
        this.Items.Add(view);
        var view2 = new CheckBoxViewModel("Image2.Jpg", "Image 2");
        this.Items.Add(view2);
    }
}

Флажок и просмотр изображения

<UserControl.Resources>
    <local:MainViewModel x:Key="MainViewModel" />
    <local:MainViewModel x:Key="ViewModel" />
    <local:BoolToVisibility x:Key="BoolToVisibility" />
</UserControl.Resources>
<Grid >
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="20*"/>
        <ColumnDefinition Width="201*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <CheckBox Command="{Binding Checked}" HorizontalAlignment="Center" VerticalAlignment="Center" IsChecked="{Binding Path=IsChecked, UpdateSourceTrigger=PropertyChanged, Mode=OneWayToSource}" Content="{Binding ImageName}" />
    <Image Grid.Column="1" Source="{Binding ImageSource}" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="{Binding IsChecked, Converter={StaticResource BoolToVisibility}}" />
</Grid>

Основной вид

    <Window.Resources>
    <local:MainViewModel x:Key="MainViewModel" />
    <DataTemplate DataType="{x:Type local:CheckBoxViewModel}">
        <local:view/>
    </DataTemplate>
</Window.Resources>
<Grid>
    <ListView DataContext="{StaticResource MainViewModel}" ItemsSource="{Binding Items}"/>
</Grid>

Таким образом модель основного представления добавляет CheckBoxViewModels к своим элементам, а затем основное представление автоматически добавляет дочернее представление к представлению списка.

Что примечательно, так это то, как переключается видимость изображений , Я использовал конвертер значений, который вы добавляете в Связывание видимости изображений. Это преобразует истинное ложное значение в тип видимости.

 public class BoolToVisibility : IValueConverter
{
    /// <summary>
    /// Converts a value.
    /// </summary>
    /// <param name="value">The value produced by the binding source.</param>
    /// <param name="targetType">The type of the binding target property.</param>
    /// <param name="parameter">The converter parameter to use.</param>
    /// <param name="culture">The culture to use in the converter.</param>
    /// <returns>A converted value. If the method returns null, the valid null value is used.</returns>
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value != null)
        {
            if ((bool)value)
            {
                return Visibility.Visible;
            }
            else
            {
                return Visibility.Collapsed;
            }
        }

        return Visibility.Collapsed;
    }

    /// <summary>
    /// Converts a value.
    /// </summary>
    /// <param name="value">The value that is produced by the binding target.</param>
    /// <param name="targetType">The type to convert to.</param>
    /// <param name="parameter">The converter parameter to use.</param>
    /// <param name="culture">The culture to use in the converter.</param>
    /// <returns>A converted value. If the method returns null, the valid null value is used.</returns>
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}
...