[英]Binding a DataGridTextColumn or DataGridTemplateColumn to a foreign key
[英]Binding IsReadOnly of a DataGridTextColumn to a DataGridTemplateColumn checkbox IsChecked
基本上,我有一个DataGrid
几个栏目,我想启用(改变IsReadOnly
属性)一个DataGridTextColumn
基于一个CheckBox
IsChecked
,位于另一个DataGridTemplateColumn
相同的DataGrid
。
这是代码的(重要部分):
<DataGrid Name="lstTags" Grid.Row="0" ItemsSource="{Binding Path = LinesCollection}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False" SelectionMode="Single" LostFocus="lstTags_LostFocus" SelectionChanged="lstTags_SelectionChanged">
<DataGrid.Columns>
<DataGridTemplateColumn x:Name="colAutoScale" Header="Auto Scale">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox x:Name="ckbAutoScale" HorizontalAlignment="Center" IsChecked="{Binding AutoScale, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Scale" Binding="{Binding Path=Scale}" IsReadOnly="{Binding ElementName ckbAutoScale, Path=IsChecked}" Width="60" />
</DataGrid.Columns>
</DataGrid>
值得一提的是,我还想反转IsChecked属性的值,即
IsChecked = true
=> IsReadOnly = false
; IsChecked = false
=> IsReadOnly = true
。 我可能会用一个简单的Converter
实现此目的,但是我需要第一部分工作。
编辑:
回答一个好问题,我的目标是禁用相邻的单元格 (同一行),而不是整个列。
这类问题确实是Model-View-ViewModel(MVVM)模式存在的原因。
使用MVVM,您可以绑定到具有支持视图所需的确切属性的视图模型。 这使模型可以更加关注需要保留哪些数据。
因此,对于您的问题,您需要创建一个LineViewModel
,看起来像这样:
public class LineViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private bool _isAutoScale;
private double _scale;
public bool IsAutoScale
{
get { return _isAutoScale; }
set
{
if (value == _isAutoScale) return;
_isAutoScale = value;
OnPropertyChange("IsAutoScale");
OnPropertyChange("IsReadOnly");
}
}
public double Scale
{
get { return _scale; }
set
{
if (value == _scale) return;
_scale = value;
OnPropertyChange("Scale");
}
}
public bool IsReadOnly => !IsAutoScale;
private void OnPropertyChange(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
同时,您还想创建一个称为MainWindowViewModel
的父视图模型(或对您的情况有意义的东西)。 这是一个非常原始的版本:
public class MainWindowViewModel : INotifyPropertyChanged
{
private List<LineViewModel> _lineViewModels;
public event PropertyChangedEventHandler PropertyChanged;
public List<LineViewModel> LineViewModels
{
get { return _lineViewModels; }
set
{
if (value == _lineViewModels) return;
_lineViewModels = value;
OnPropertyChange("LineViewModels");
}
}
public MainWindowViewModel()
{
LineViewModels = new[]
{
new { AutoScale = false, Scale = 0.2 },
new { AutoScale = true, Scale = 0.3 },
new { AutoScale = false, Scale = 0.4 },
}
.Select(
x => new LineViewModel
{
IsAutoScale = x.AutoScale,
Scale = x.Scale
})
.ToList();
}
private void OnPropertyChange(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
最后,您将更新XAML文件,使其看起来像这样:
<Window x:Class="Sandbox.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:sandbox="clr-namespace:Sandbox"
mc:Ignorable="d"
Title="MainWindow"
Height="350"
Width="525">
<Window.DataContext>
<sandbox:MainWindowViewModel />
</Window.DataContext>
<DataGrid ItemsSource="{Binding LineViewModels}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
AutoGenerateColumns="False"
CanUserAddRows="False"
CanUserDeleteRows="False"
SelectionMode="Single">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Auto Scale">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox HorizontalAlignment="Center"
IsChecked="{Binding IsAutoScale}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Auto Scale">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Scale}"
IsReadOnly="{Binding IsReadOnly}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Window>
因此,基本上,对于视图逻辑MainWindow
由下式确定MainWindowViewModel
并为各行的视图逻辑DataGrid
由受控LineViewModel
。
请注意,可以使用诸如MVVM Light Toolkit和PropertyChanged.Fody之类的库/ NuGet包来简化实现INotifyPropertyChanged
的许多样板。
将以下绑定用于“ Scale
Column
:
<DataGridTextColumn Header="Scale" Binding="{Binding Path=Scale}" Width="60" >
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="IsEnabled" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGridCellsPanel}},Path=Children[0].Content.Content.AutoScale}" />
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
或者简单地
<DataGridTextColumn Header="Scale" Binding="{Binding Path=Scale}" Width="60" >
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="IsEnabled" Value="{Binding Path=AutoScale}" />
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
输出:
PS:以上解决方案1特定于您的代码,因为“
Auto Scale
column
位于0Index
,这就是为什么我在Binding
使用Children[0]
的原因。 如果有任何上下文需要,请更改。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.