当组合值设置为值- MVVM时,禁用WPF数据网格中的单元格
本文关键字:数据网 数据 网格 WPF 单元格 禁用 设置 组合 MVVM | 更新日期: 2023-09-27 18:06:13
我有一个具有DataGridComboBoxColumn
列的DataGrid,我需要启用或禁用另一列中的复选框单元格,但我的代码似乎不起作用。
我有以下代码定义我的组合列:
<DataGridComboBoxColumn Header="Location"
SelectedValueBinding="{Binding LocationId, Mode=TwoWay}"
SelectedValuePath="LocationId"
DisplayMemberPath="LocationText"
TextBinding="{Binding Location, Mode=TwoWay}">
这是我的复选框列的代码:
<DataGridCheckBoxColumn Header="Active"
Binding="{Binding IsActive}">
<DataGridCheckBoxColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedLineItem.Location}"
Value="01">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridCheckBoxColumn.CellStyle>
</DataGridCheckBoxColumn>
我已经添加了一个DataTrigger来尝试检测何时Location字段更改为01,并且基于此,我试图禁用选中行的复选框单元格,但它不起作用。
我还需要根据其他值选中/取消选中组合。
你知道我该怎么做吗?
更新1:好吧,我已经取得了一些进展(侥幸!),现在我的触发器正在踢,但由于某种原因,每当我改变我的下拉位置为选定单元格,它改变了所有行的值相同的值。
下面是我的下拉栏的完整代码:
<DataGridComboBoxColumn Header="Location"
SelectedItemBinding="{Binding DataContext.SelectedLineItem.SelectedLocation,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},
Mode=TwoWay}"
SelectedValuePath="LocationId"
DisplayMemberPath="LocationText"
TextBinding="{Binding Location, Mode=TwoWay}">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding DataContext.Locations,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"/>
<Setter Property="IsReadOnly" Value="True"/>
<Setter Property="FontSize" Value="14"/>
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding DataContext.Locations,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}}"/>
<Setter Property="SelectedItem" Value="{Binding DataContext.SelectedLocation,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}}"/>
<Setter Property="IsReadOnly" Value="False"/>
<Setter Property="IsEditable" Value="True"/>
<Setter Property="FontSize" Value="14"/>
<EventSetter Event="KeyUp" Handler="LocationColumn_KeyUp"></EventSetter>
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsDropDownOpen" Value="true" />
</Trigger>
</Style.Triggers>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
这里是我的复选框列的完整代码(不要担心触发器做什么-它们是测试触发器):
<DataGridCheckBoxColumn Header="Active" Binding="{Binding IsActive}">
<DataGridCheckBoxColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedLocation.LocationId}" Value="1">
<Setter Property="Background" Value="Green" />
</DataTrigger>
<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="" >
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="01" >
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="02" >
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="03" >
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridCheckBoxColumn.CellStyle>
</DataGridCheckBoxColumn>
谁能弄清楚为什么我所有的行现在被设置,当我改变一个组合值?
谢谢。
感谢@Freeman为我们指出了正确的方向。
我最终弄清楚了,我设法完全让它工作的唯一方法是在XAML中设置属性并在我的ViewModel中应用一些基本逻辑的组合。
完整的解释如下:
我有一个DataGridComboBoxColumn
绑定到我的SelectionLocation
属性,属于我的行ViewModel
get { return this._selectedLocation; }
set { Set(() => SelectedLocation, ref this._selectedLocation, value); }
现在关于XAML中的绑定:
<DataGridComboBoxColumn Header="Location"
SelectedItemBinding="{Binding SelectedLocation, Mode=TwoWay}"
SelectedValuePath="LocationId"
DisplayMemberPath="LocationText">
这是我的第一个问题,因为每当我从组合中选择一个项目时,它没有调用/触发我的SelectedLocation ViewModel的setter部分。通过添加UpdateSourceTrigger=PropertyChanged
:
<DataGridComboBoxColumn Header="Warehouse"
SelectedItemBinding="{Binding SelectedLocation, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
SelectedValuePath="LocationId"
DisplayMemberPath="LocationText">
关于复选框列,XAML定义为:
<DataGridCheckBoxColumn Header="Active" Binding="{Binding IsActive, Mode=TwoWay>
<DataGridCheckBoxColumn.ElementStyle>
<Style TargetType="CheckBox">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
</DataGridCheckBoxColumn.ElementStyle>
</DataGridCheckBoxColumn>
再次,当选中和取消选中我的复选框时,它没有触发我的IsActive属性的setter,它属于与'SelectedLocation'属性相同的ViewModel。
为了解决这个问题,我最终添加了UpdateSourceTrigger=PropertyChanged
:
<DataGridCheckBoxColumn Header="Active" Binding="{Binding IsActive, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}">
<DataGridCheckBoxColumn.ElementStyle>
<Style TargetType="CheckBox">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
</DataGridCheckBoxColumn.ElementStyle>
</DataGridCheckBoxColumn>
现在已经对Combo和复选框列的绑定问题进行了排序,还剩下一件事。有条件的选择。这是通过使用XAML中的DataTrigger
和我的ViewModel中的代码的组合来排序的。
XAML负责启用/禁用复选框,就像从SelectedLocation:
中选择一样<DataGridCheckBoxColumn Header="Active" Binding="{Binding IsActive, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}">
<DataGridCheckBoxColumn.ElementStyle>
<Style TargetType="CheckBox">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="01" >
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="02" >
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="03" >
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridCheckBoxColumn.ElementStyle>
</DataGridCheckBoxColumn>
在我的ViewModel中,每当SelectedLocation setter被触发时,它现在应用相同的规则,即检查位置是否为01,02或03,它将设置我的IsActive属性,因此选择/取消选中复选框:
public LocationViewModel SelectedLocation
{
get { return this._selectedLocation; }
set
{
Set(() => SelectedLocation, ref this._selectedLocation, value);
if (this._selectedLocation.LocationText == "01")
this.IsActive = false;
else if (this._selectedLocation.LocationText == "02")
this.IsActive = true;
else if (this._selectedLocation.LocationText == "03")
{
this.IsActive = false;
}
}
}
这显然不是理想的,但它的工作完全符合预期。理想的解决方案是根据XAML中的条件将IsChecked
设置为true或false,如下所示:
<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="02" >
<Setter Property="IsChecked" Value="True" />
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
但无论出于何种原因,当我使用这个方法时,当我手动选中复选框时,它将触发IsActive
setter,但它不会基于触发规则触发它,从而使这个属性无用,我不能拥有。
我不得不发布一个更新作为我的惊喜,而复选框被禁用使用
<DataGridCheckBoxColumn Header="Active" Binding="{Binding IsActive, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}">
<DataGridCheckBoxColumn.ElementStyle>
<Style TargetType="CheckBox">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="01" >
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="02" >
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="03" >
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridCheckBoxColumn.ElementStyle>
</DataGridCheckBoxColumn>
只是暂时禁用。双击单元格实际上启用了单元格,然后重新启用了复选框!完全没有意义,让你禁用一个复选框,然后在单元格进入编辑模式时重新启用它!!
无论如何,幸运的是,有一个工作是禁用单元格而不是复选框。这可以通过使用CellStyle
而不是ElementStyle
:
<DataGridCheckBoxColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="01" >
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="02" >
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="03" >
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridCheckBoxColumn.CellStyle>
您正在将复选框绑定到SelectedLineItem.Location。但是我可以看到这个属性没有绑定到组合框的任何地方。你已经将组合框的TextBinding绑定到Location。尝试将其更改为SelectedILineItem。还有位置。然后复选框将被绑定到组合框中的键入值。
如果你想根据组合框的选择值启用/禁用复选框,要么你应该将组合框的SelectedValuePath绑定到这个属性,要么将你的复选框绑定到SelectedItem。和触发条件,以匹配组合框的绑定。
如果我正确理解了你的问题,我认为你可以尝试这种方式。我在一个组合框中绑定了一个国家列表,并根据选择的某个值禁用了另一列。
Xaml代码看起来像
<Window.Resources>
<staticData:CountryList x:Key="CountryList"/>
</Window.Resources>
<Grid>
<DataGrid ItemsSource="{Binding SampleList}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Countries" Width="100">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding SelectedCountry}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox Height="22" Grid.Row="0"
ItemsSource="{StaticResource CountryList}"
SelectedItem="{Binding SelectedCountry}">
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
<!-- Inputs -->
<DataGridTextColumn Width="SizeToCells" Header="Inputs" MinWidth="100" Binding="{Binding Input}" >
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedCountry}" Value="UK">
<Setter Property="IsEnabled" Value="false"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
Viewmodel有
public class MainViewModel : ObservableObject
{
private List<SampleData> sampleList;
public List<SampleData> SampleList
{
get { return sampleList; }
set { Set(ref sampleList, value); }
}
private Country selectedItem;
public Country SelectedItem
{
get { return selectedItem; }
set { selectedItem = value; }
}
private ObservableCollection<Country> countries;
public ObservableCollection<Country> CountriesList
{
get { return countries; }
set { this.Set(ref countries, value); }
}
public MainViewModel()
{
CountriesList = new ObservableCollection<Country> { new Country { Id = 1, Name = "India" }, new Country { Id = 1, Name = "Australia" } };
SampleList = new List<SampleData>
{
new SampleData
{
Input = "shan", RowNum = 3, SelectedCountry = "India"
},
new SampleData
{
Input = "raj", RowNum = 1, SelectedCountry = "India"
},
new SampleData
{
Input = "sfk", RowNum = 9, SelectedCountry = "India"
},
new SampleData
{
Input = "ShanSfk", RowNum = 7, SelectedCountry = "India"
}
};
}
}
和列表
public class CountryList : List<string>
{
public CountryList()
{
this.Add("India");
this.Add("Australia");
this.Add("UK");
}
}
根据组合框中国家的选择,单元格被启用或禁用。