简体   繁体   English

DataTemplate ListBox 中的 CheckBox 绑定和使用 MVVM 的触发器

[英]CheckBox's in DataTemplate ListBox Binding and Triggers using MVVM

I'm learning how to use MVVM and how bind data inside a WPF App.我正在学习如何使用 MVVM 以及如何在 WPF 应用程序中绑定数据。 I've created a custom CheckedListBox in XAML file this way:我以这种方式在 XAML 文件中创建了一个自定义 CheckedListBox:

        <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>

and also I want a single Image to dynamically show up for each CheckBox I check.并且我还希望为我检查的每个 CheckBox 动态显示单个图像。 I understand that I need to use Binding and UpdateSourceTrigger Property but I'm not sure how to realize this.我知道我需要使用 Binding 和 UpdateSourceTrigger 属性,但我不确定如何实现这一点。 What should I add here so that my app does what I want?我应该在这里添加什么,以便我的应用程序执行我想要的操作?

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

Here's a part of my C# code for the ViewModel:这是我用于 ViewModel 的 C# 代码的一部分:

    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; }
            }
        }
...

Thank you for any recommendation.感谢您的任何建议。

One eazy way to do ProperyChanged events is to use the base set for ViewModelBase this.Set because it will raise the changed event for you.执行 ProperyChanged 事件的一种简单方法是使用 ViewModelBase this.Set 的基集,因为它会为您引发已更改的事件。

to do this I split up the view model and view in to 2, one for the main view and one for a view combining the check box and image.为此,我将视图模型和视图拆分为 2 个,一个用于主视图,另一个用于组合复选框和图像的视图。 You can do it with one like you have but it was just easier for me.你可以用一个像你一样的人来做,但对我来说更容易。

View Model for the CheckBox and image 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); }
    }
}

Main Window View Model主窗口视图模型

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);
    }
}

Checkbox and image view复选框和图像视图

<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>

Main View主视图

    <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>

This way the main view model adds CheckBoxViewModels to its items and then the main view automatically adds the child view to the list view.这样,主视图模型将 CheckBoxViewModels 添加到其项目,然后主视图自动将子视图添加到列表视图。

Whats notable is how the images visibility is flipped.值得注意的是图像可见性是如何翻转的。 I used a value converter that you add to the Images visibility Binding.我使用了您添加到图像可见性绑定的值转换器。 It will convert a true false value to a type of Visibility.它会将真假值转换为可见性类型。

 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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM