我有一个类似于以下帖子的问题:
我需要在Silverlight DataGrid中有一个列,基于ViewModel中的一个值,它是visibile/折叠的。为了实现这一点,我尝试将可见性属性绑定到ViewModel。但是,我很快发现可见性属性不是DependencyProperty,因此不能绑定它。
为了解决这个问题,我尝试将我自己的DataGridTextColumn子类化。使用这个新类,我创建了一个DependencyProperty,它最终推动了对DataGridTextColumn.Visibility属性的更改。如果我不做数据库的话,这很好用。当我将数据库绑定到我的新属性时,它就会失败,只有一个AG_E_PARSER_BAD_PROPERTY_VALUE例外。
public class MyDataGridTextColumn : DataGridTextColumn
{
#region public Visibility MyVisibility
public static readonly DependencyProperty MyVisibilityProperty =
DependencyProperty.Register("MyVisibility", typeof(Visibility), typeof(MyDataGridTextColumn), new PropertyMetadata(Visibility.Visible, OnMyVisibilityPropertyChanged));
private static void OnMyVisibilityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var @this = d as MyDataGridTextColumn;
if (@this != null)
{
@this.OnMyVisibilityChanged((Visibility)e.OldValue, (Visibility)e.NewValue);
}
}
private void OnMyVisibilityChanged(Visibility oldValue, Visibility newValue)
{
Visibility = newValue;
}
public Visibility MyVisibility
{
get { return (Visibility)GetValue(MyVisibilityProperty); }
set { SetValue(MyVisibilityProperty, value); }
}
#endregion public Visibility MyVisibility
}
下面是XAML的一个小片段。
<DataGrid ....>
<DataGrid.Columns>
<MyDataGridTextColumn Header="User Name"
Foreground="#FFFFFFFF"
Binding="{Binding User.UserName}"
MinWidth="150"
CanUserSort="True"
CanUserResize="False"
CanUserReorder="True"
MyVisibility="{Binding Converter={StaticResource BoolToVisibilityConverter}, Path=ShouldShowUser}"/>
<DataGridTextColumn .../>
</DataGrid.Columns>
</DataGrid>
几个重要的事实。
有人知道为什么这不管用吗?
发布于 2010-09-20 17:50:15
这是我想出的解决方案,用一个小黑客。
首先,您需要从DataGrid继承。
public class DataGridEx : DataGrid
{
public IEnumerable<string> HiddenColumns
{
get { return (IEnumerable<string>)GetValue(HiddenColumnsProperty); }
set { SetValue(HiddenColumnsProperty, value); }
}
public static readonly DependencyProperty HiddenColumnsProperty =
DependencyProperty.Register ("HiddenColumns",
typeof (IEnumerable<string>),
typeof (DataGridEx),
new PropertyMetadata (HiddenColumnsChanged));
private static void HiddenColumnsChanged(object sender,
DependencyPropertyChangedEventArgs args)
{
var dg = sender as DataGrid;
if (dg==null || args.NewValue == args.OldValue)
return;
var hiddenColumns = (IEnumerable<string>)args.NewValue;
foreach (var column in dg.Columns)
{
if (hiddenColumns.Contains ((string)column.GetValue (NameProperty)))
column.Visibility = Visibility.Collapsed;
else
column.Visibility = Visibility.Visible;
}
}
}
DataGridColumn及其后代的DataGridEx类添加了一个新的DP,用于根据x:Name隐藏列。
要在您的XAML中使用:
<my:DataGridEx x:Name="uiData"
DataContext="{Binding SomeDataContextFromTheVM}"
ItemsSource="{Binding Whatever}"
HiddenColumns="{Binding HiddenColumns}">
<sdk:DataGridTextColumn x:Name="uiDataCountOfItems">
Header="Count"
Binding={Binding CountOfItems}"
</sdk:DataGridTextColumn>
</my:DataGridEx>
您需要将这些添加到您的ViewModel或您使用的任何数据上下文中。
private IEnumerable<string> _hiddenColumns;
public IEnumerable<string> HiddenColumns
{
get { return _hiddenColumns; }
private set
{
if (value == _hiddenColumns)
return;
_hiddenColumns = value;
PropertyChanged (this, new PropertyChangedEventArgs("HiddenColumns"));
}
}
public void SomeWhereInYourCode ()
{
HiddenColumns = new List<string> {"uiDataCountOfItems"};
}
若要取消隐藏,只需从列表中删除相应的名称,或在未隐藏名称的情况下重新创建该名称。
发布于 2010-10-20 01:05:42
对于这个问题,我有另一个解决方案,它使用类似于您在DataGridTextColumn上找到的“绑定”属性的方法。由于列类是DependencyObjects,所以不能直接对它们进行数据库处理,但是如果添加对实现INotifyPropertyChanged的FrameworkElement的引用,则可以将绑定传递给元素,然后使用依赖项属性通知列绑定已更改。
需要注意的一点是,在列本身而不是网格上绑定可能意味着要使用DataContextProxy访问要绑定可见性的字段(列绑定将默认为ItemSource的作用域)。
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace XYZ.Controls
{
public class ExtendedDataGridTextColumn : DataGridTextColumn
{
private readonly Notifier _e;
private Binding _visibilityBinding;
public Binding VisibilityBinding
{
get { return _visibilityBinding; }
set
{
_visibilityBinding = value;
_e.SetBinding(Notifier.MyVisibilityProperty, _visibilityBinding);
}
}
public ExtendedDataGridTextColumn()
{
_e = new Notifier();
_e.PropertyChanged += ToggleVisibility;
}
private void ToggleVisibility(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Visibility")
this.Visibility = _e.MyVisibility;
}
//Notifier class is just used to pass the property changed event back to the column container Dependency Object, leaving it as a private inner class for now
private class Notifier : FrameworkElement, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public Visibility MyVisibility
{
get { return (Visibility)GetValue(MyVisibilityProperty); }
private set { SetValue(MyVisibilityProperty, value); }
}
public static readonly DependencyProperty MyVisibilityProperty = DependencyProperty.Register("MyVisibility", typeof(Visibility), typeof(Notifier), new PropertyMetadata(MyVisibilityChanged));
private static void MyVisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var n = d as Notifier;
if (n != null)
{
n.MyVisibility = (Visibility) e.NewValue;
n.PropertyChanged(n, new PropertyChangedEventArgs("Visibility"));
}
}
}
}
}
发布于 2009-06-26 20:11:36
datagrid列继承自DependencyObject而不是FrameworkElement。在WPF里这没什么大不了的..。但是在silverlight中,您只能绑定到FrameworkElement对象。因此,当您尝试时,您将得到AG_E_PARSER_BAD_PROPERTY_VALUE的描述性错误消息。
https://stackoverflow.com/questions/1045014
复制相似问题