![](/img/trans.png)
[英]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.