【发布时间】:2015-05-07 08:16:38
【问题描述】:
在 WPF 中,使用 MVVM 模型,我正在努力解决我认为是绑定问题的问题。我有一个 ListView 旨在显示对象的集合。 ItemsSource 绑定到集合,每个 GridViewColumn 绑定到该对象的单独属性。此视图(UserControl)在主窗口的TabControl 中的多个选项卡中是通用的。每个选项卡都需要隐藏某些列(逻辑发生在ViewModel)。
我创建了一个 Behaviors 类来为多个事物附加 DependecyProperties,包括用于 GridViewColumn 的属性 IsHidden。考虑到这一点,下面是一个示例设置:
行为类 - 最小化示例
public static class LayoutColumn
{
public static readonly DependencyProperty HiddenProperty = DependencyProperty.RegisterAttached(
"IsHidden",
typeof(bool),
typeof(LayoutColumn));
public static bool GetIsHidden(DependencyObject obj)
{
return (bool)obj.GetValue(HiddenProperty);
}
public static void SetIsHidden(DependencyObject obj, bool isHidden)
{
obj.SetValue(HiddenProperty, isHidden);
}
public static bool IsHidden(this GridViewColumn column)
{
bool? isHidden = column.GetProperty<bool>(HiddenProperty);
// Debug
string format = "{0}.IsHidden = {1}";
if (isHidden.HasValue)
{
Console.WriteLine(format, column.Header, isHidden.Value);
}
else
{
Console.WriteLine(format, column.Header, "Null");
}
return isHidden.HasValue && isHidden.Value;
}
private static T? GetProperty<T>(this GridViewColumn column, DependencyProperty dp) where T : struct
{
if (column == null)
{
throw new ArgumentNullException("column");
}
object value = column.ReadLocalValue(dp);
if (value != null && value.GetType() == dp.PropertyType)
{
return (T)value;
}
return null;
}
} // end LayoutColumn class
public class LayoutManager
{
// Methods and logic to enforce column min/max width, hidden, fixed, etc by attaching to the ListView and GridViewColumn event handlers.
}
一个示例对象类
public class Example
{
public string Foo { get; set; }
public string Bar { get; set; }
public string Baz { get; set; }
}
视图模型
public class MyDisplayViewModel : INotifyPropertyChanged
{
private bool hidden;
private ObservableCollection<Example> examples;
...
public bool HideColumn
{
get
{
return this.hidden;
}
set
{
this.hidden = value;
this.OnPropertyChanged("HideColumn");
}
}
public ObservableCollection<Example> ExampleCollection
{
get
{
return this.examples;
}
set
{
this.examples = value;
this.OnPropertyChanged("ExampleCollection");
}
}
}
一些 XAML
<ListView
Name="LogListView"
ItemsSource="{Binding ExampleCollection}"
ListViewBehaviors:LayoutManager.Enabled="{Binding AttachProperty}">
<ListView.View>
<GridView>
<GridViewColumn
Width="Auto"
ListViewBehaviors:LayoutColumn.MinWidth="40"
ListViewBehaviors:LayoutColumn.MaxWidth="200"
ListViewBehaviors:LayoutColumn.IsHidden="True"
DisplayMemberBinding="{Binding Foo, Mode=OneWay}"
Header="Hidden Column"/>
<GridViewColumn
Width="Auto"
ListViewBehaviors:LayoutColumn.MinWidth="74"
ListViewBehaviors:LayoutColumn.MaxWidth="200"
ListViewBehaviors:LayoutColumn.IsHidden="False"
DisplayMemberBinding="{Binding Bar, Mode=OneWay}"
Header="Visible Column"/>
<GridViewColumn
Width="Auto"
ListViewBehaviors:LayoutColumn.IsFixed="True"
ListViewBehaviors:LayoutColumn.IsHidden="{Binding Path=DataContext.HideColumn, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}},
Mode=OneWay}"
DisplayMemberBinding="{Binding Baz, Mode=OneWay}"
Header="Dynamic Visibility">
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
在此处演示,手动将附加属性 IsHidden 设置为 true 或 false 可以正确隐藏/显示关联的列。当IsHidden 为空(该列未设置附加行为)时,预期的行为是该列正常显示。
问题
绑定列总是默认显示,这对我来说意味着IsHidden没有被设置。我觉得我已经很接近了,但是我所有的研究结果都是我在这里所做的例子。我对 WPF 还很陌生,所以我不知道还要搜索什么。
编辑
我尝试了以下方法,但都失败了:
AncestorType={x:Type ListView}
AncestorType={x:Type UserControl}
AncestorType={x:Type Window}
我需要做什么才能将 GridViewColumn 附加属性绑定到 ViewModel HideColumn 属性?
【问题讨论】:
-
请分享您的行为。还有你的视图模型。可能您需要将 RelativeSource 设置为 Window 或 Usercontrol
-
@Ganesh 我在 ViewModel 中进行了编辑。我没有添加行为类,因为那会很臃肿,而且我已经知道它在手动设置真/假时有效。还测试了
UserControl和Window,但遗憾的是都失败了。 -
绑定肯定会起作用(您可以通过在 HideColumn 的 getter 上放置断点来验证)。最有可能的隐藏逻辑不适用于适当的绑定。您能否发布该代码以及如何隐藏该列?
-
有可能直到您检查 IsHidden() 时才解决绑定问题。如果可能的话,你能把代码示例上传到云端吗?