【发布时间】:2011-01-03 01:28:57
【问题描述】:
我需要根据绑定模型上的属性将我的一些 WPF Datagrid 行显示为只读或不只读。
如何做到这一点?
【问题讨论】:
标签: wpf datagrid wpftoolkit readonly
我需要根据绑定模型上的属性将我的一些 WPF Datagrid 行显示为只读或不只读。
如何做到这一点?
【问题讨论】:
标签: wpf datagrid wpftoolkit readonly
我遇到了同样的问题。 使用 jsmith 的回答和 Nigel Spencer 的博客中提供的信息,我提出了一个解决方案,不需要更改 WPF DataGrid 源代码、子类化或添加代码到视图的代码隐藏。如您所见,我的解决方案对 MVVM 非常友好。
它使用Expression Blend Attached Behavior mechanism,因此您需要安装Expression Blend SDK 并添加对Microsoft.Expression.Interactions.dll 的引用,但如果您不喜欢这种行为,可以轻松地将其转换为native attached behavior。
<DataGrid
xmlns:Behaviors="clr-namespace:My.Common.Behaviors"
...
>
<i:Interaction.Behaviors>
<Behaviors:DataGridRowReadOnlyBehavior/>
</i:Interaction.Behaviors>
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsReadOnly}" Value="True"/>
<Setter Property="Behaviors:ReadOnlyService.IsReadOnly" Value="True"/>
<Setter Property="Foreground" Value="LightGray"/>
<Setter Property="ToolTipService.ShowOnDisabled" Value="True"/>
<Setter Property="ToolTip" Value="Disabled in ViewModel"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
...
</DataGrid>
using System.Windows;
namespace My.Common.Behaviors
{
internal class ReadOnlyService : DependencyObject
{
#region IsReadOnly
/// <summary>
/// IsReadOnly Attached Dependency Property
/// </summary>
private static readonly DependencyProperty BehaviorProperty =
DependencyProperty.RegisterAttached("IsReadOnly", typeof(bool), typeof(ReadOnlyService),
new FrameworkPropertyMetadata(false));
/// <summary>
/// Gets the IsReadOnly property.
/// </summary>
public static bool GetIsReadOnly(DependencyObject d)
{
return (bool)d.GetValue(BehaviorProperty);
}
/// <summary>
/// Sets the IsReadOnly property.
/// </summary>
public static void SetIsReadOnly(DependencyObject d, bool value)
{
d.SetValue(BehaviorProperty, value);
}
#endregion IsReadOnly
}
}
using System;
using System.Windows.Controls;
using System.Windows.Interactivity;
namespace My.Common.Behaviors
{
/// <summary>
/// Custom behavior that allows for DataGrid Rows to be ReadOnly on per-row basis
/// </summary>
internal class DataGridRowReadOnlyBehavior : Behavior<DataGrid>
{
protected override void OnAttached()
{
base.OnAttached();
if (this.AssociatedObject == null)
throw new InvalidOperationException("AssociatedObject must not be null");
AssociatedObject.BeginningEdit += AssociatedObject_BeginningEdit;
}
private void AssociatedObject_BeginningEdit(object sender, DataGridBeginningEditEventArgs e)
{
var isReadOnlyRow = ReadOnlyService.GetIsReadOnly(e.Row);
if (isReadOnlyRow)
e.Cancel = true;
}
protected override void OnDetaching()
{
AssociatedObject.BeginningEdit -= AssociatedObject_BeginningEdit;
}
}
}
【讨论】:
我找到了几个简单的解决方案来解决这个问题。我认为最好的方法是连接到 DataGrid 的BeginningEdit 事件。这类似于 Nigel Spencer 在他的帖子中所做的,但您不必从 DataGrid 中覆盖它。这个解决方案很棒,因为它不允许用户编辑该行中的任何单元格,但它确实允许他们选择行。
在代码后面:
private void MyList_BeginningEdit(object sender, DataGridBeginningEditEventArgs e)
{
if (((MyCustomObject)e.Row.Item).IsReadOnly) //IsReadOnly is a property set in the MyCustomObject which is bound to each row
{
e.Cancel = true;
}
}
在 XAML 中:
<DataGrid ItemsSource="{Binding MyObservableCollection}"
BeginningEdit="MyList_BeginningEdit">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}"
Header="Name"/>
<DataGridTextColumn Binding="{Binding Age}"
Header="Age"/>
</DataGrid.Columns>
</DataGrid>
不同的解决方案...这根本不允许用户选择行,但不需要在后面的代码中添加额外的代码。
<DataGrid ItemsSource="{Binding MyObservableCollection}">
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsReadOnly}"
Value="True" >
<Setter Property="IsEnabled"
Value="False" /> <!-- You can also set "IsHitTestVisble" = False but please note that this won't prevent the user from changing the values using the keyboard arrows -->
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}"
Header="Name"/>
<DataGridTextColumn Binding="{Binding Age}"
Header="Age"/>
</DataGrid.Columns>
</DataGrid>
【讨论】:
我认为最简单的方法是将 IsReadOnly 属性添加到 DataGridRow 类。 Nigel Spencer 有一篇关于如何做到这一点的详细文章here。
【讨论】: