简体   繁体   English

C# WPF - 绑定到 DataGrid 中的父视图模型不起作用

[英]C# WPF - Binding to parent-ViewModel within DataGrid not working

I am trying to access a binding to my ViewModels' DependencyProperty from within a DataGrid after it is binded to an itemssource.在绑定到项目源后,我试图从 DataGrid 中访问对我的 ViewModel 的 DependencyProperty 的绑定。 While from outside the DataGrid Bindings work well and Bindings within the DataGrid work for elements of the Itemssource well too, I am not able to get a binding to my viewModel within the DataGrid.虽然从 DataGrid 外部绑定工作良好,并且 DataGrid 中的绑定也适用于 Itemssource 的元素,但我无法在 DataGrid 中绑定到我的 viewModel。 I tried several aproaches.我尝试了几种方法。

I want to use that non-working binding to achieve: - load the column-header via a dependency Property from the viewModel - load a bool Value from the ViewModel which determines whether a column is read-only我想使用该非工作绑定来实现: - 通过 viewModel 中的依赖属性加载列标题 - 从 ViewModel 加载一个 bool 值,以确定列是否为只读

This is one of my DependencyProperties I have specified in the ViewModel:这是我在 ViewModel 中指定的 DependencyProperties 之一:

public static readonly DependencyProperty FirstColDataGridLabelProperty = DependencyProperty.Register(
            "FirstColDataGridLabel", typeof(string), typeof(MyVm), new PropertyMetadata(default(string)));

In the constructor of the viewlModel some values are assigned to the dependencyProperties.在 viewlModel 的构造函数中,一些值被分配给了 dependencyProperties。

Edit: Added the bounding grid and UserControl-Tag to the Data-Grid: MyList is a List, containing the data (FirstCol, SecondCol, etc.)编辑:将边界网格和 UserControl-Tag 添加到数据网格:MyList 是一个列表,包含数据(FirstCol、SecondCol 等)

<UserControl x:Class="Aidb.GeoMonPlus.Wpf.Control.EditSpatialReferenceListControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:viewModel="clr-namespace:Aidb.GeoMonPlus.ViewModel.Control;assembly=Aidb.GeoMonPlus.ViewModel"
             Width="Auto"
             Height="Auto"
             MinWidth="400"
             MinHeight="200"
             mc:Ignorable="d" 
             d:DesignHeight="400" d:DesignWidth="1000"
             x:Name="myControl">
    <Grid>
<DataGrid Grid.Column="0" Grid.Row="0"
    ItemsSource="{Binding MyList}"
    CanUserResizeColumns="True"
    CanUserResizeRows="True"
    CanUserSortColumns="True"
    CanUserAddRows="False"
    AlternatingRowBackground="Gainsboro"
    AlternationCount="2"
    AutoGenerateColumns="False"
    BorderBrush="Black"
    GridLinesVisibility="Vertical">
    <DataGrid.Columns>
        <DataGridTextColumn Header="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type viewModel:MyVm}}, Path=FirstColDataGridLabel}" Binding="{Binding FirstCol}" Width="Auto" IsReadOnly="True"/>
        <DataGridTextColumn Header="{Binding SecondColDataGridLabel, FallbackValue='AnzeigeraumbezugDataGridLabel'}" Binding="{Binding (viewModel:EditSpatialReferenceListVm.GCSDataGridLabel) }" Width="Auto" IsReadOnly="True"/>
        <DataGridTextColumn Header="{Binding (viewModel:MyVm.ThirdColDataGridLabel)}" Binding="{Binding ThirdCol}" Width="Auto" IsReadOnly="True"/>
        <DataGridTextColumn Header="{Binding ElementName=myControl, Path=DataContext.FourthColDataGridLabel}" Binding="{Binding FourthCol}" Width="Auto" IsReadOnly="True">
            <DataGridTextColumn.CellStyle>
                <Style TargetType="DataGridCell">
                    <Setter Property="Margin" Value="0,0,-1,0"></Setter>
                </Style>
            </DataGridTextColumn.CellStyle>
        </DataGridTextColumn>
    </DataGrid.Columns>
</DataGrid>
<Button Grid.Column="0" Grid.Row="1"
    Margin="0,20,0,20"
    Width="75"
    Height="Auto"
    HorizontalAlignment="Left"
    VerticalAlignment="Center"
    Command="{Binding BtnShowSubmit}"
    Content="{Binding BtnShowLabel, FallbackValue='BtnShowLabel'}" />

None of the four tries for a dataBinding for the header-names are working.对标头名称进行数据绑定的四次尝试都没有奏效。 All headers of the table are empty or the fallback-value is shown.表的所​​有标题都为空或显示了后备值。

The binding of the itemssource works, data is shown as expected in the datagrid.项目源的绑定有效,数据在数据网格中按预期显示。 The binding in the button to show the buttons text works as expected.按钮中显示按钮文本的绑定按预期工作。

Is this just not possible for DataGrid or how do I access ViewModels' DependecyProperties from inside the dataGrid after it was binded to an itemssource?这对于 DataGrid 是不可能的,还是在绑定到项目源后如何从 dataGrid 内部访问 ViewModels 的 DependecyProperties?

Edit2: As it was asked, this is my ViewModels Base Class: Edit2:正如有人问的那样,这是我的 ViewModels 基类:

public class ViewModelBase : DependencyObject, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected static void PropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args)
    {
        var vmBase = sender as ViewModelBase;
        vmBase?.OnPropertyChanged(args.Property.Name);
    }

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Edit3:编辑3:

I found some errormessages:我发现了一些错误消息:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='MyProject.ViewModel.Control.EditSpatialReferenceListVm', AncestorLevel='1''. System.Windows.Data 错误:4:无法找到引用“RelativeSource FindAncestor, AncestorType='MyProject.ViewModel.Control.EditSpatialReferenceListVm', AncestorLevel='1''的绑定源。 BindingExpression:Path=GCSDataGridLabel; BindingExpression:Path=GCSDataGridLabel; DataItem=null;数据项=空; target element is 'DataGridTextColumn' (HashCode=8060118);目标元素是“DataGridTextColumn”(HashCode=8060118); target property is 'Header' (type 'Object')目标属性是“标题”(类型“对象”)

or或者

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. System.Windows.Data 错误:2:找不到目标元素的管理 FrameworkElement 或 FrameworkContentElement。 BindingExpression:Path=(viewModel:EditSpatialReferenceListVm.GCSDataGridLabel); BindingExpression:Path=(viewModel:EditSpatialReferenceListVm.GCSDataGridLabel); DataItem=null;数据项=空; target element is 'DataGridTextColumn' (HashCode=16639474);目标元素是“DataGridTextColumn”(HashCode=16639474); target property is 'Header' (type 'Object')目标属性是“标题”(类型“对象”)

Searching for this leads to that post: WPF Error: Cannot find governing FrameworkElement for target element Where it is stated out from user 'WPF-it' that:搜索此内容会导致该帖子: WPF 错误:无法找到目标元素的管理 FrameworkElement从用户“WPF-it”那里声明的内容:

Sadly any DataGridColumn hosted under DataGrid.Columns is not part of Visual tree and therefore not connected to the data context of the datagrid.遗憾的是,在 DataGrid.Columns 下托管的任何 DataGridColumn 都不是可视化树的一部分,因此没有连接到数据网格的数据上下文。

He suggest to use a proxy-control.他建议使用代理控制。

I just went through the same thing.我刚刚经历了同样的事情。 There are several methods posted for getting around this and I can see you have tried some, but none of them worked for me either except one.有几种方法可以解决这个问题,我可以看到你已经尝试了一些方法,但除了一种方法外,没有一种方法对我有用。 Create a control just above your datagrid and give it a name:在数据网格上方创建一个控件并为其命名:

<TextBlock x:Name="tempcontrol" Text="{Binding HeaderText}" Visibility="Collapsed"/>

and then bind this temp control to the data you want and set it's visibility to collapsed.然后将此临时控件绑定到您想要的数据并将其可见性设置为折叠。

Then bind your DataGridColumn to the temp controls property:然后将您的 DataGridColumn 绑定到临时控件属性:

<DataGridTextColumn Header="{Binding Path=Text, Source={x:Reference tempControl}}"/>

My case was little different because I was binding to the Visibilty property so I used a FrameworkElement instead of a TextBlock for the dummy control, but I think this should work as well.我的情况没有什么不同,因为我绑定到 Visibilty 属性,所以我使用 FrameworkElement 而不是 TextBlock 作为虚拟控件,但我认为这也应该有效。

As mentioned in the mainpost (edit 3), it indeed is not working with datagrid.正如主帖(编辑 3)中提到的,它确实不适用于数据网格。 But using DataView can handle that.但是使用 DataView 可以解决这个问题。

Using a ListView with an inner GridView instead of a DataGrid also is possible to solve that.使用带有内部 GridView 而不是 DataGrid 的 ListView 也可以解决这个问题。 With that the following bindings do work:因此,以下绑定确实有效:

<GridViewColumn Header="{Binding HoehenbezugsrahmenDataGridLabel, FallbackValue='HoehenbezugsrahmenDataGridLabel'}" DisplayMemberBinding="{Binding Hoehenbezugsrahmen}" Width="250" />
<GridViewColumn Header="{Binding ElementName=myControl, Path=DataContext.TransformationDataGridLabel, FallbackValue='AnzPunkteGeoMonDataGridLabel'}" DisplayMemberBinding="{Binding Transformation}" Width="250" />
<GridViewColumn Header="{Binding Path=Text, Source={x:Reference tmpHeader}}" DisplayMemberBinding="{Binding AnzPunkteGeoMon}" Width="250" />


<GridViewColumn DisplayMemberBinding="{Binding Ursprungsraumbezug}" Width="250">
    <GridViewColumn.HeaderTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding ElementName=myControl, Path=DataContext.TransformationDataGridLabel, FallbackValue='AnzPunkteGeoMonDataGridLabel'}"/>
        </DataTemplate>
    </GridViewColumn.HeaderTemplate>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Ursprungsraumbezug}" Width="250">
    <GridViewColumn.HeaderTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=Text, Source={x:Reference tmpHeader}}"/>
        </DataTemplate>
    </GridViewColumn.HeaderTemplate>
</GridViewColumn>

All other mentioned bindings do not work, headers keep being empty.所有其他提到的绑定都不起作用,标题一直为空。 Again using Ancestor does not work.再次使用 Ancestor 不起作用。

Especially the first approach is the shortest one.特别是第一种方法是最短的。 Due to this I am going to change from DataGrid to ListView.因此,我将从 DataGrid 更改为 ListView。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM