如何在XAML中选中复选框?

时间:2019-01-02 12:44:26

标签: c# wpf xaml checkbox

我有一个对象列表,为ObservableCollection<MyObject>。我已经能够使用DataGrid中的XAML在组合框中显示这些对象的 name 属性。

现在,我有另一个对象AnotherObject,该对象的属性定义为字符串列表,并且该列表的每个项目都是上述MyObject的 name 属性。

在组合框中,我要显示复选框前面的MyObject.name属性。 假设复选框中有30个项目,而AnotherObject.names的实例保存其中的三个项目。 现在,我要选择与AnotherObject.names中的三个项目相同的那些项目的复选框。

我该如何实现?

某些代码:

MyObjectViewModel.cs:

public class MyObjectViewModel
{
    private MyObject _myObject;

    public MyObjectViewModel(MyObject myObject)
    {
        this._myObject = myObject;
    }

    public MyObject MyObject
    {
        get
        {
            return _myObject;
        }
        set
        {
            _myObject = value;
        }
    }

    public string Name
    {
        get { return _myObject.Name;  }
        set
        {
            _myObject.Name = value;
        }
    }

    public override string ToString()
    {
        return Name;
    }
}

AnotherObjectRowViewmodel.cs:

public class AnotherObjectRowViewModel : INotifyPropertyChanged
{
    private AnotherObject _anotherObject;
    private ObservableCollection<MyObjectViewModel> _myObjects;

    public AnotherObjectRowViewModel(AnotherObject anotherObject, ObservableCollection<MyObjectViewModel> myObjects)
    {
        this._anotherObject = anotherObject;
        this._myObjects = myObjects;
    }

    public AnotherObject AnotherObject
    {
        get
        {
            return _anotherObject;
        }
        set
        {
            this._anotherObject = value;
        }
    }

    public string Name
    {
        get { return _anotherObject.Name; }
        set { _anotherObject.Name = value; }
    }

    public ObservableCollection<MyObjectViewModel> MyObjects {
        get
        {
            return this._myObjects;
        }
        set
        {
            _myObjects = value;
        }
    }

    event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
    {
        add
        {
            //throw new NotImplementedException();
        }

        remove
        {
            //throw new NotImplementedException();
        }
    }
}

这就是我在XAML文件中尝试过的方法:

<DataGridTemplateColumn x:Name="NamesColumn" Header="Names">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Grid>
                <ComboBox Name="Name" DataContext="{Binding}" ItemsSource="{Binding Path=myObjects}" IsEditable="True" IsReadOnly="True" 
                          VerticalAlignment="Center" SelectionChanged="OnDetailParamsSelectionChanged" >
                    <ComboBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <CheckBox x:Name="chbNames" Width="20" VerticalAlignment="Center" Checked="OnChbDetailParamsCheckBoxChecked" Unchecked="OnChbDetailParamsCheckBoxChecked"></CheckBox>
                                <TextBlock DataContext="{Binding Path=MyObject}" Text="{Binding Path=Name, Converter={StaticResource StringListConverter}}" VerticalAlignment="Center" />
                            </StackPanel>
                        </DataTemplate>
                    </ComboBox.ItemTemplate>
                </ComboBox>
            </Grid>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

示例: 组合框包含30个名称(Name1,...,Name30)的列表;

AnotherObject.names是{Name1,Name2,Name4,Name7};

在组合框中,所选项目应为Name1,Name2,Name4,Name7。其他所有项目均应保持未选中状态。

更新2019-01-06: 这意味着组合框的ItemsSource = {Binding}是 MyObject ,但是选中的项目应存储在 AnotherObject 中。这就是为什么每当我勾选复选框时都会得到此异常的原因:

System.Windows.Data Error: 40 : BindingExpression path error: 'xxx' property not found on 'object' ''MyObjectViewModel' (HashCode=34649765)'. BindingExpression:Path=xxx.DetailParams; DataItem='MyObjectViewModel' (HashCode=34649765); target element is 'CheckBox' (Name='chbDetailParams'); target property is 'IsChecked' (type 'Nullable`1')

我的XAML包含根据 IsItemsSelectedConverter 的以下代码段:

<UserControl.Resources>
    <ctb:IsItemSelectedConverter x:Key="IsItemSelectedConverter"/>
</UserControl.Resources>

IsChecked复选框的属性如下:

IsChecked="{Binding Path=Names, Mode=TwoWay, Converter={StaticResource IsItemSelectedConverter}}"

但是它不起作用。调试该代码后,永远不会使用IsItemsSelectedConverter。

2 个答案:

答案 0 :(得分:0)

MyObject的视图模型中创建一个布尔属性,即在MyObjectViewModel中创建一个布尔属性,如果NameAnotherObject的名称列表中,则会返回一个值。 / p>

答案 1 :(得分:0)

创建一个IsItemSelectedConverter并传入数据模型中的对象列表。在新类中实现IValueConverter,并将每个复选框的IsChecked属性绑定到两件事:value应该是当前项目,而parameter应该是项目列表。转换器应确定当前项目是否在项目列表中,并返回适当的布尔值。

您将必须创建要使用的UI转换器实例。我通常在一个单独的资源字典中定义转换器,该转换器对所有XAML文件全局可用。

我的IsItemSelectedConverter看起来像这样:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {

            if (value is MyObjectViewModel objectViewModel && parameter is AnotherObjectRowViewModel anotherObjectRowViewModel)
            {
                return anotherObjectRowViewModel.MyObjects.Contains(objectViewModel);
            }
            return false;
        }

在XAML上,我的CheckBox代码如下:<CheckBox IsChecked="{Binding Mode=OneWay, Converter={StaticResource converter}, ConverterParameter={StaticResource viewModel} }" />

请注意:代码中存在一些问题,将阻止它按原样运行,但是我假设这些是复制和粘贴实际代码的产物。