我需要在不破坏MVVM(没有代码隐藏/事件)的情况下完成以下任务。我有一个带有CheckBox列和TextBox列的DataGrid。如果选中该复选框,我想将TextBox的TextDecorations属性更改为Strikethrough。虽然编译器不讨厌我的XAML,但它不起作用。我的DataGridTextBoxColumn的XAML如下:
<DataGridTextColumn Header="Item Description" Binding="{Binding Path=ItemDescription, Mode=TwoWay}" Width="175">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="TextAlignment" Value="Center" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=complete, Path=IsChecked}" Value="True">
<Setter Property="TextDecorations" Value="Strikethrough"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
答案 0 :(得分:0)
由于 ItemsSource 中的每个元素,DataGrid在运行时创建自己的TextBlock和CheckBox,因此无法通过名称绑定到此元素。相反,您应该将 CheckBox 的Value和 TextBlock 的样式设置器绑定到您的模型。例如,你有这样的Model和ViewModel:
<强>型号:强>
public class SomeModel : INotifyPropertyChanged
{
private string textField;
private bool boolField;
public event PropertyChangedEventHandler PropertyChanged;
public string TextField
{
get { return textField; }
set
{
if (value == textField) return;
textField = value;
OnPropertyChanged();
}
}
public bool BoolField
{
get { return boolField; }
set
{
if (value.Equals(boolField)) return;
boolField = value;
OnPropertyChanged();
}
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
<强>视图模型:强>
public class MainViewModel : INotifyPropertyChanged
{
private ObservableCollection<SomeModel> models;
public ObservableCollection<SomeModel> Models
{
get { return models; }
set
{
if (Equals(value, models)) return;
models = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
public MainViewModel()
{
Models = new ObservableCollection<SomeModel>();
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
所以现在你可以将模型的 BoolField 绑定到 CheckBox 的Value和 TextBlock 的View Setters in View:
<强> MainView.cs:强>
public partial class MainView : Window
{
public MainView()
{
InitializeComponent();
var mv = new MainViewModel
{
Models = { new SomeModel { BoolField = true, TextField = "One" }, new SomeModel { TextField = "Two" } },
};
DataContext = mv;
}
}
<强> MainView.xaml:强>
<Window x:Class="WpfDataGridCols.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainView" Height="350" Width="525">
<Grid>
<DataGrid ItemsSource="{Binding Models}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding TextField}">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="TextAlignment" Value="Center" />
<Style.Triggers>
<!--Pay attention on this:-->
<DataTrigger Binding="{Binding BoolField}" Value="True">
<Setter Property="TextDecorations" Value="Strikethrough"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridCheckBoxColumn Binding="{Binding BoolField}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>