如何将DataContext绑定到窗口资源中的ViewModel对象



我正在尝试将我的用户控制数据上下文绑定到视图模型对象。由于未知原因,在窗口内设置DataContext。资源因此提供

系统。Windows。数据错误:3:找不到提供的元素DataContext。BindingExpression:Path=AreaFilter;DataItem=null;

在window.resources之外设置相同的数据上下文非常有效。一段代码应该能把事情弄清楚:

<Window>
<Window.Resources>
    <GridViewColumnCollection x:Key="eventColumns">
        <GridViewColumn DisplayMemberBinding="{Binding Path=Area}">
            <GridViewColumn.Header>
                <v:FilterV DataContext="{Binding AreaFilter}"/> <!--here is the problem-->
            </GridViewColumn.Header>
        </GridViewColumn>
    </GridViewColumnCollection>
</Window.Resources>
<Grid>
    <v:FilterV DataContext="{Binding AreaFilter}"/> <!-- here it works OK -->
    <GridViewHeaderRowPresenter Name="listHeader" Columns="{StaticResource eventColumns}"/>
</Grid>

FilterV是一个UserControl,我目前将其简化为只显示一个文本块。在网格内部,它显示区域过滤器。名称没有问题。在这两种情况下设置DataContext有什么区别?如何解决?

我相信GridViewColumn实际上不是VisualTree的一部分,所以其中的绑定不起作用,因为它在评估绑定时没有DataContext或源。

您可以尝试使用引用GridViewRelativeSource绑定来设置DataContext

<GridViewColumn.HeaderTemplate>
    <DataTemplate>
        <v:FilterV DataContext="{Binding DataContext.AreaFilter, 
            RelativeSource={RelativeSource AncestorType={x:Type GridView}}}"/>
    </DataTemplate>
</GridViewColumn.HeaderTemplate>

尽管如果这不起作用,我找到的唯一解决方法是在.Resources中创建一个包含您要查找的绑定的Freezeable对象,然后将v:FilterV.DataContext设置为静态资源

<GridView.Resources>
    <local:BindingProxy x:Key="proxy" 
        Data="{Binding AreaFilter, ElementName=MyGridView}" />
</DataGrid.Resources>
...
<GridViewColumn.HeaderTemplate>
    <DataTemplate>
        <v:FilterV DataContext="{Binding Source={StaticResource proxy}}"/>
    </DataTemplate>
</GridViewColumn.HeaderTemplate>

你可以在这里查看的例子

此外,您应该将GridViewHeaderTemplate属性设置为包含<v:FilterV />控件的DataTemplate,而不是像现在这样直接在.Content属性中设置它。将Content直接设置为对象意味着任何使用该样式的项都将尝试在Content中使用相同的控件,因此,如果您有多个对象应用该Content属性,它将引发异常,因为项只能属于一个父控件

最新更新