Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MVVM下的WPF DataGridTemplateColumn可见性绑定_Wpf_Binding_Mvvm_Datagrid_Wpfdatagrid - Fatal编程技术网

MVVM下的WPF DataGridTemplateColumn可见性绑定

MVVM下的WPF DataGridTemplateColumn可见性绑定,wpf,binding,mvvm,datagrid,wpfdatagrid,Wpf,Binding,Mvvm,Datagrid,Wpfdatagrid,我的ViewModel中有一个绑定到ICollectionView的DataGrid。DataGrid位于UserControl内部,UserControl用于几个不同的数据场景,其中一些场景需要特定的DataGrid列,而其他场景则不需要 我只想将DataGridTemplateColumn的Visibility属性绑定到内部标签的Content属性,这样,如果所有行都不包含值,它将被隐藏。我设置了一个字符串到可见性转换器,但无法找到内部标签的内容属性 <DataGridTemplate

我的ViewModel中有一个绑定到ICollectionView的DataGrid。DataGrid位于UserControl内部,UserControl用于几个不同的数据场景,其中一些场景需要特定的DataGrid列,而其他场景则不需要

我只想将DataGridTemplateColumn的Visibility属性绑定到内部标签的Content属性,这样,如果所有行都不包含值,它将被隐藏。我设置了一个字符串到可见性转换器,但无法找到内部标签的内容属性

<DataGridTemplateColumn Header="Groups" Width="*" CanUserSort="True" SortMemberPath="Groups" Visibility="{Binding ElementName=lbl, Path=Content, Converter={StaticResource StringToVisibilityConverter}}">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Label Name="lbl" Content="{Binding Path=Groups}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>


有什么建议吗?

通过ViewModel上的
属性可以更好地实现这一点;因为无论怎样,
标签
最终都是这样使用的

<DataGridTemplateColumn Header="Groups" Width="*" CanUserSort="True" SortMemberPath="Groups" Visibility="{Binding Groups, Converter={StaticResource SomeConverter}}">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Label Name="lbl" Content="{Binding Path=Groups}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>


您不能这样做。绑定/名称解析不能以这种方式工作。为什么不使用
StringToVisibilityConverter
创建一个
CollectionToVisibilityConverter
,它检查数据源(可能传入要检查的列/属性),查看该列/属性是否完全为空,然后将其转换为可见性?

我在堆栈溢出的某个地方读到了(找不到确切的帖子)DataGridColumn没有分配数据上下文,因为它们不是FrameworkElement。要解决这个问题,我必须使用与此类似的代码:

    <DataGridTemplateColumn 
         Header="Groups" 
         Width="*" 
         CanUserSort="True" 
         SortMemberPath="Groups" 
         Visibility"{Binding RelativeSource={x:Static RelativeSource.Self}, 
                        Path=(FrameworkElement.DataContext).IsGroupsVisible, 
                        Converter={StaticResource booleanToVisiblityConverter}}">
         <DataGridTemplateColumn.CellTemplate>         
              <DataTemplate>             
                   <Label Name="lbl" Content="{Binding Path=Groups}" />         
              </DataTemplate>     
         </DataGridTemplateColumn.CellTemplate> 
    </DataGridTemplateColumn> 

Where 

<UserControl.Resources>
    <BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter" /> 
</UserControl.Resources>

哪里

要使用
相对资源.Self
作为
数据网格模板列的
相对资源
绑定,您需要将添加到应用程序中。这对于WPF 4数据网格仍然是必需的

<DataGridTemplateColumn 
         Header="Groups" 
         Width="*" 
         CanUserSort="True" 
         SortMemberPath="Groups" 
         Visibility"{Binding RelativeSource={x:Static RelativeSource.Self}, 
                        Path=(FrameworkElement.DataContext).IsGroupsVisible, 
                        Converter={StaticResource booleanToVisiblityConverter}}">
         <DataGridTemplateColumn.CellTemplate>         
              <DataTemplate>             
                   <Label Name="lbl" Content="{Binding Path=Groups}" />         
              </DataTemplate>     
         </DataGridTemplateColumn.CellTemplate> 
    </DataGridTemplateColumn> 

100感谢SliverNinja和本文。源代码的链接已经不起作用,无法下载,因此我编写了自己的附件,使其适用于所有可能的情况(DataContext更改、附件属性值更改、添加列)

我的应用程序将DataGrid与AutoGenerateColumns=False一起使用,并使用DataGridTemplateColumn,因此DataContext是在将列添加到网格之前设置的

以下是附加的属性类别:

public sealed class DataGridColumnDataContextForwardBehavior
{
    private DataGrid dataGrid = null;

    public DataGridColumnDataContextForwardBehavior(DataGrid dataGrid)
    {
        this.dataGrid = dataGrid;

        dataGrid.Columns.CollectionChanged += DataGridColumns_CollectionChanged;
    }

    private void DataGridColumns_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        var IsDataContextForwardingEnabled = GetIsDataContextForwardingEnabled(dataGrid);

        if (IsDataContextForwardingEnabled && dataGrid.DataContext != null)
        {
            if (e.Action == NotifyCollectionChangedAction.Add)
            {
                foreach (DataGridColumn column in e.NewItems)
                {
                    column.SetValue(FrameworkElement.DataContextProperty, dataGrid.DataContext);
                }
            }
        }
    }

    static DataGridColumnDataContextForwardBehavior()
    {
        FrameworkElement.DataContextProperty.AddOwner(typeof(DataGridColumn));
        FrameworkElement.DataContextProperty.OverrideMetadata(typeof(DataGrid), 
            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits, new PropertyChangedCallback(OnDataContextChanged)));
    }

    public static readonly DependencyProperty IsDataContextForwardingEnabledProperty = 
        DependencyProperty.RegisterAttached("IsDataContextForwardingEnabled", typeof(bool), typeof(DataGridColumnDataContextForwardBehavior), 
            new FrameworkPropertyMetadata(false, OnIsDataContextForwardingEnabledChanged));

    public static void OnDataContextChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        DataGrid dataGrid = obj as DataGrid;
        if (dataGrid == null) return;

        var IsDataContextForwardingEnabled = GetIsDataContextForwardingEnabled(dataGrid);
        if (IsDataContextForwardingEnabled)
        {
            foreach (DataGridColumn col in dataGrid.Columns)
            {
                col.SetValue(FrameworkElement.DataContextProperty, e.NewValue);
            }
        }
    }

    static void OnIsDataContextForwardingEnabledChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        var dataGrid = obj as DataGrid;
        if (dataGrid == null) return;

        new DataGridColumnDataContextForwardBehavior(dataGrid);

        if (!(e.NewValue is bool)) return;

        if ((bool)e.NewValue && dataGrid.DataContext != null)
            OnDataContextChanged(obj, new DependencyPropertyChangedEventArgs(FrameworkElement.DataContextProperty, dataGrid.DataContext, dataGrid.DataContext));
    }

    public static bool GetIsDataContextForwardingEnabled(DependencyObject dataGrid)
    {
        return (bool)dataGrid.GetValue(IsDataContextForwardingEnabledProperty);
    }

    public static void SetIsDataContextForwardingEnabled(DependencyObject dataGrid, bool value)
    {
        dataGrid.SetValue(IsDataContextForwardingEnabledProperty, value);
    }
}
另一个不明显的问题是如何正确使用DataGridTemplateColumn的绑定:

<DataGrid bhv:DataGridColumnDataContextForwardBehavior.IsDataContextForwardingEnabled="True">
<DataGrid.Columns>
<DataGridTemplateColumn Visibility="{Binding Path=DataContext.Mode, RelativeSource={RelativeSource Self}, Converter={StaticResource SharedFilesModeToVisibilityConverter}, ConverterParameter={x:Static vmsf:SharedFilesMode.SharedOut}}"/>

使用Path=DataContext.MyProp和relativesourceself是很重要的


在当前的实现中,我唯一不喜欢的事情就是处理DataGrid.Columns.CollectionChanged事件,我创建了我的类的实例,并且没有保留对它的引用。因此理论上GC可能会在时间内杀死它,目前不确定如何正确处理它,稍后会考虑它并更新我的帖子。欢迎任何想法和评论

大家好,我已经试过了,在运行时遇到了这个错误:System.Windows.Data错误:2:找不到目标元素的治理FrameworkElement或FrameworkContentElement。BindingExpression:Path=Groups;DataItem=null;目标元素是“DataGridTemplateColumn”(HashCode=38907373);目标属性是“可见性”(类型“可见性”)令人沮丧的是,当我使用XAML中定义的CollectionViewSource时,通过将可见性绑定源设置为CollectionViewSource,这实际上起到了作用。我必须将CollectionViewSource移动到ViewModel中以处理排序/筛选,这打破了此可见性绑定。还有其他想法吗?CollectionViewSource是C的XAML代理CollectionView。在您的ViewModel中返回ICollectionView ala…CollectionViewSource.GetDefaultView(您的集合)抱歉,我的错误,这是我从ViewModel返回的数据网格的ItemsSource,它抛出了“System.Windows.Data Error:2”关于可见性绑定。我甚至尝试绑定到ViewModel中的一个专用属性,但它仍然找不到。这是在编译时…或运行时?它是否击中了您的转换器?嗨,Andy,很有趣。现在没有收到任何绑定错误,但它仍然不工作。转换器甚至没有被调用…是ViewMod上的一个属性吗是DataGrid绑定到的属性?还是DataGrid中的行绑定到的单个项上的属性?我假设两者都是,因为您希望在单个单元格中显示文本,并且网格中列的可见性只能绑定到一个属性。它是DataGrid中单个项上的属性llection设置为CollectionViewSource的源,并作为ICollectionView返回到DataGrid。我还尝试将其绑定到ViewModel上的一个名为IsGroupsVisible的属性权限,该属性不太优雅,但它也无法识别。我已将上述代码更改为使用IsGroupsVisible属性。它甚至没有调用ViewModel属性!我开始认为这是一个WPF错误。当我放置相同的代码时:Visibility=“{Binding RelativeSource={x:Static RelativeSource.Self},Path=(FrameworkElement.DataContext).IsGroupVisibility,Converter={StaticResource BootVisibilityConverter}”在我看来,在任何其他控件上,它都可以完美地工作。任何想要找到答案的人,请参阅