c# - DataGridComboBoxColumn ItemsSource 列表未找到

标签 c# wpf datagrid

这是绑定(bind)到列的类。我在 ListParts 上设置了监视,这些部件确实存在。

private MasksSourceList _MasksSourceListBound;
public MasksSourceList MasksSourceListBound
{
    get => _MasksSourceListBound;
    set { SetAndNotify(ref _MasksSourceListBound, value, () => MasksSourceListBound); }
}

public class MasksSourceList : ObservableObject
{
    private List<MaskDetail> _maskDetails;
    public List<MaskDetail> MaskDetails
    {
        get => _maskDetails;
        set { SetAndNotify(ref _maskDetails, value, () => MaskDetails); }
    }

    private List<Jarvis.Data.Models.Parts> _listParts;
    public List<Jarvis.Data.Models.Parts> ListParts
    {
        get => _listParts;
        set { SetAndNotify(ref _listParts, value, () => ListParts); }
    }
}

下面是显示 DataGrid 父项源的 XAML。

<DataGrid  ItemsSource="{Binding MasksSourceListBound.MaskDetails}" >

我显示了一个普通的文本列来演示 DataGrid 的 ItemsSource 绑定(bind)正在工作,如附图所示。

<DataGrid.Columns>
    <DataGridTextColumn Header="part name"  Binding="{Binding PartName}">

    </DataGridTextColumn>

    <DataGridComboBoxColumn 
        Header="part name" 
        ItemsSource="{Binding MasksSourceListBound.ListParts}"
        SelectedValueBinding="{Binding PartName, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
        SelectedValuePath="PartId"
        DisplayMemberPath="PartName" 
        >
    </DataGridComboBoxColumn>

但是为什么组合框列的 ItemsSource 无法识别 ListParts?我检查了 PartId 和 PartName 的拼写,它们是正确的。

这是输出窗口中的错误消息:

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=MasksSourceListBound.ListParts; DataItem=null; target element is 'DataGridComboBoxColumn' (HashCode=64358720); target property is 'ItemsSource' (type 'IEnumerable')

enter image description here

我已经尝试过这个,但仍然没有结果:

<DataGridComboBoxColumn.ElementStyle>
    <Style TargetType="ComboBox">
        <Setter Property="ItemsSource" Value="{Binding MasksViewModel.MasksSourceListBound.ListParts}"/>
    </Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
    <Style TargetType="ComboBox">
        <Setter Property="ItemsSource" Value="{Binding MasksViewModel.MasksSourceListBound.ListParts}"/>
    </Style>
</DataGridComboBoxColumn.EditingElementStyle>

使用 DataContext.MasksSourceListBound.ListParts 和适当的相对源等修改上述内容后。跟踪器显示:

System.Windows.Data Warning: 58 :   Path: 'DataContext.MasksSourceListBound.ListParts'
System.Windows.Data Warning: 60 : BindingExpression (hash=20088760): Default mode resolved to OneWay
System.Windows.Data Warning: 61 : BindingExpression (hash=20088760): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 62 : BindingExpression (hash=20088760): Attach to System.Windows.Controls.DataGridComboBoxColumn+TextBlockComboBox.ItemsSource (hash=46581119)
System.Windows.Data Warning: 66 : BindingExpression (hash=20088760): RelativeSource (FindAncestor) requires tree context
System.Windows.Data Warning: 65 : BindingExpression (hash=20088760): Resolve source deferred
System.Windows.Data Warning: 67 : BindingExpression (hash=5618098): Resolving source 
System.Windows.Data Warning: 70 : BindingExpression (hash=5618098): Found data context element: <null> (OK)

Here is the corrected XAML Decided to explicitly set the datacontext for DataGrid to avoid 3 part binding. But still getting Input String was not in correct format in break mode. The output indicates RelativeSource (FindAncestor) requires tree context:

<DataGrid DataContext="{Binding MasksSourceListBound}" ItemsSource="{Binding MaskDetails}"

  <DataGridComboBoxColumn Header="part name" HeaderStringFormat="             {0}" Width="200" 

                                            SelectedValueBinding="{Binding PartName, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                                            SelectedValuePath="PartId"
                                            DisplayMemberPath="PartName">
                        <DataGridComboBoxColumn.ElementStyle>
                            <Style TargetType="ComboBox">
                                <Setter 
                                    Property="ItemsSource" 
                                    Value="{Binding DataContext.ListParts, RelativeSource={RelativeSource AncestorType=DataGrid}, PresentationTraceSources.TraceLevel=High}"
                                />
                            </Style>
                        </DataGridComboBoxColumn.ElementStyle>
                        <DataGridComboBoxColumn.EditingElementStyle>
                            <Style TargetType="ComboBox">
                                <Setter 
                                    Property="ItemsSource" 
                                    Value="{Binding DataContext.ListParts, RelativeSource={RelativeSource AncestorType=DataGrid}, PresentationTraceSources.TraceLevel=High}"
                                />
                            </Style>
                        </DataGridComboBoxColumn.EditingElementStyle>
                    </DataGridComboBoxColumn>

最佳答案

所以我们已经成功了一半。 ElementStyle 和 EditingElementStyle 中的绑定(bind)的 DataContext 是行项 - MaskDetail(在您的情况下)。我的猜测是这个绑定(bind):

Value="{Binding MasksViewModel.MasksSourceListBound.ListParts}"

...意味着建议绑定(bind)应该找到 MasksViewModel 类型的 View 模型并使用其中的指定属性。

一方面,这不是绑定(bind)的工作原理。它们有一个 DataContext,如果您没有显式指定 SourceRelativeSource,它们会在那里查找属性。该绑定(bind)所发生的情况是,它正在查看一个 MaskDetail,即您用于填充网格的行项目类,其名称为 MasksViewModel 的属性。我认为没有,否则这会起作用。

以下是找出绑定(bind)失败原因的方法:

Value="{Binding MasksViewModel.MasksSourceListBound.ListParts, PresentationTraceSources.TraceLevel=High}"

然后在运行时观察 VS 中的输出 Pane 。当绑定(bind)尝试查找 MasksViewModel.MasksSourceListBound.ListParts 时,您将获得每个步骤的跟踪,并且您将看到失败的位置和原因。

因此,在元素样式中,您要做的就是绑定(bind)到 ListParts,它是 MasksSourceListBound 的属性,而后者又是主视图模型的属性 - - 这是 DataGridDataContext

因此,我们在可视化树中搜索 DataGrid,获取其 DataContext,然后在其中查找 MasksSourceListBound.ListParts:

<DataGridComboBoxColumn.ElementStyle>
    <Style TargetType="ComboBox">
        <Setter 
            Property="ItemsSource" 
            Value="{Binding DataContext.MasksSourceListBound.ListParts, RelativeSource={RelativeSource AncestorType=DataGrid}}"
            />
    </Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
    <Style TargetType="ComboBox">
        <Setter 
            Property="ItemsSource" 
            Value="{Binding DataContext.MasksSourceListBound.ListParts, RelativeSource={RelativeSource AncestorType=DataGrid}}"
            />
    </Style>
</DataGridComboBoxColumn.EditingElementStyle>

它并不漂亮,但它始终如一地工作,这就是我们在 WPF 中做事的方式。

更新

这是我的 XAML 的更完整图片。我没有完全重现你的整个事情。重要的部分是相对源绑定(bind):我可以使用以下 XAML 绑定(bind)到 DataGrid 的 DataContext 的属性。 DataGrid 的 DataContext 是对主视图模型的引用 - 拥有 MasksSourceListBound.MaskDetails 的同一对象。

<DataGrid
    ItemsSource="{Binding MasksSourceListBound.MaskDetails}"
    >
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding OtherTestProperty}" />
        <DataGridComboBoxColumn 
            Header="Test" 
            SelectedItemBinding="{Binding SelectedItem}"
            >
            <DataGridComboBoxColumn.ElementStyle>
                <Style TargetType="ComboBox">
                    <Setter 
                        Property="ItemsSource" 
                        Value="{Binding DataContext.MasksSourceListBound.ListParts, RelativeSource={RelativeSource AncestorType=DataGrid}, PresentationTraceSources.TraceLevel=High}" 
                        />
                </Style>
            </DataGridComboBoxColumn.ElementStyle>
            <DataGridComboBoxColumn.EditingElementStyle>
                <Style TargetType="ComboBox">
                    <Setter Property="ItemsSource" Value="{Binding DataContext.MasksSourceListBound.ListParts, RelativeSource={RelativeSource AncestorType=DataGrid}}" />
                </Style>
            </DataGridComboBoxColumn.EditingElementStyle>
        </DataGridComboBoxColumn>
    </DataGrid.Columns>

关于c# - DataGridComboBoxColumn ItemsSource 列表未找到,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44463000/

相关文章:

c# - 以编程方式在 CheckListBox 中设置选中的项目

c# - 通用冒泡排序扩展

wpf - WPF中的GridView动态列宽

c# - DataGrid - 更改编辑行为

wpf - 如何在 WPF 数据网格中启用 NewItem Placeholder

c# - 当我将 DATE 类型的参数传递给 Crystal 报表时,为什么会生成错误消息 "Invalid Parameter Value"?

c# - 在 .NET Core 中运行 NUnit 测试

c# - 无法将 DateTime 从 EF "Code First"保存到 MySQL 远程数据库

c# - 排序后保留数据网格中的选定行

wpf - 在 DataGrid 的选定行中设置元素的前景色