【问题标题】:DataGridComboBoxColumn ItemsSource List Not Found未找到 DataGridComboBoxColumn ItemsSource 列表
【发布时间】:2017-11-11 18:41:48
【问题描述】:

这是绑定到列的类。我在 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 绑定正在工作,如附图所示。

<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 错误:2:找不到目标元素的管理 FrameworkElement 或 FrameworkContentElement。 BindingExpression:Path=MasksSourceListBound.ListParts;数据项=空;目标元素是“DataGridComboBoxColumn”(HashCode=64358720);目标属性是“ItemsSource”(类型“IEnumerable”)

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

<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)

这是更正后的 XAML 决定为 DataGrid 显式设置数据上下文以避免 3 部分绑定。但是在中断模式下仍然得到输入字符串的格式不正确。输出表明 RelativeSource (FindAncestor) 需要树上下文:

&lt;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>

【问题讨论】:

  • “目标元素”是拥有绑定目标的对象。这里是DataGridComboBoxColumn。 “找不到目标元素的管理 FrameworkElement 或 FrameworkContentElement。”意味着它没有可视父级来继承 DataContextIt's a common problem with that column type.
  • 我刚刚测试了使用 ElementStyle 和 EditElementStyle 设置 ItemsSource 那里。尝试寻找祖先来获取父数据上下文。但仍然没有结果。 MasksSourceListBound 位于作为 DataContext 的 MasksViewModel 内。您能否提供示例 XAML?
  • 示例 XAML 在我链接的答案中。 MasksViewModel 是从哪里来的?
  • MasksViewModel 是页面的DataContext。

标签: c# wpf datagrid


【解决方案1】:

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

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

...表示绑定应该找到MasksViewModel 类型的视图模型并使用其中的指定属性。

一方面,绑定不是这样工作的。他们有一个DataContext,如果您没有明确指定SourceRelativeSource,他们会在那里寻找该属性。该绑定发生的情况是它正在查看 MaskDetail,即您用于填充网格的行项目类,用于名为 MasksViewModel 的属性。我不认为有一个,否则这会起作用。

这是找出绑定失败原因的方法:

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

然后在运行时观察 VS 中的输出窗格。当绑定尝试查找 MasksViewModel.MasksSourceListBound.ListParts 时,您将获得每个步骤的跟踪信息,并且您会看到它在哪里以及为什么会失败。

因此,在元素样式中,您要做的是绑定到ListPartsMasksSourceListBound 的属性,而这又是主视图模型的属性——即DataGrid 的@ 987654335@.

所以我们将可视化树搜索到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 的更完整图片。我没有完全重现你的整个事情。重要的部分是相对源绑定:我可以使用以下 XAML 绑定到 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>

【讨论】:

  • 使用此示例,我收到一条 Exception Unhandled 消息:输入字符串的格式不正确。因此,我删除了 DataContext 这个词并留在了 MasksSourceListBound.ListParts 中,它消除了异常消息,但正如预期的那样没有结果。仍然需要以某种方式找到数据上下文。
  • 我必须看看你做了什么才能知道它有什么问题。我对“输入字符串的格式不正确”有疑问。我从它工作的测试项目中粘贴了该代码。
  • 当你输入 'DataContext' 是那个文字还是你的意思是 MyDataContext 名称?
  • 相对源绑定将Binding的源更改为DataGrid控件。 DataGrid 控件有一个名为DataContext 的属性。如果ItemsSource 的绑定有效,则DataContext 属性引用了您的主视图模型。
  • 感谢您使用 XAML 引导我朝着正确的方向前进。然后我只需要将 SelectedValuePath 更改为 PartName,因为 MaskDetail 只有名称而不是 Id。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-14
  • 1970-01-01
  • 1970-01-01
  • 2013-12-12
  • 2017-01-16
  • 1970-01-01
相关资源
最近更新 更多