How to access parent's DataContext from a User

2020-02-06 05:47发布

I need to access the container's DataContext from a UserControl (a grid containing textboxes and a listbox: I need to insert items in this list box) that I created in WPF: which is the best way to do it?

I was thinking to pass the DataContext as parameter to user control but think there is a cleaner way to do it.

4条回答
做个烂人
2楼-- · 2020-02-06 06:20

Normally the DataContext will be inherited, just do not explicitly set it on the UserControl and it will get it from its parent. If you have to set it you could still use the Parent property to get the parent, which you then can safe-cast to a FrameworkElement and if it is not null you can grab its DataContext.

查看更多
霸刀☆藐视天下
3楼-- · 2020-02-06 06:21

H.B. answers the question in your title.

However the text poses a different design question. I'd ask you to reconsider your design.

A control inherits the DataContext property of its ancestor as long as no one in between explicitly overrides.
If the user control needs data, it should get it from its data source (a viewmodel for the user control). So in this case, the user control can obtain the data it needs from the ListItemsForDisplay property exposed on the SomeViewModel instance. No need to get parent and cast.. much cleaner.

<ContainerType DataSource={Binding SomeViewModel}>
  <YourUserControl>
    <ListBox ItemsSource={Binding ListItemsForDisplay}"/>
...
查看更多
对你真心纯属浪费
4楼-- · 2020-02-06 06:26

Add this BindingProxy class to your project:

using System.Windows;

namespace YourNameSpace
{
    /// <summary>
    /// Add Proxy <ut:BindingProxy x:Key="Proxy" Data="{Binding}" /> to Resources
    /// Bind like <Element Property="{Binding Data.MyValue, Source={StaticResource Proxy}}" />   
    /// </summary>
    public class BindingProxy : Freezable
    {
        protected override Freezable CreateInstanceCore()
        {
            return new BindingProxy();
        }

        public object Data
        {
            get { return (object)GetValue(DataProperty); }
            set { SetValue(DataProperty, value); }
        }

        public static readonly DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy));
    }
}
  1. Add the BindingProxy to your UserControl's resources.
  2. Set the 'Data' property of the BindingProxy to whatever you need, e.g. search for a parent Window. Data="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},Path=DataContext}" If you needed something more complex you could use a custom converter.

Now you have access to that parent's DataContext: {Binding Data.MyCommand, Source={StaticResource BindingProxy}}

<UserControl 
         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:common="clr-namespace:YourNameSpace;assembly=YourAssembly"
         mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300">
    <UserControl.Resources>
        <common:BindingProxy x:Key="BindingProxy" Data="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},Path=DataContext}" />
    </UserControl.Resources>
    <Border>
        <Button Command="{Binding Data.MyCommand, Source={StaticResource BindingProxy}}">Execute My Command</Button>
        <!-- some visual stuff -->
    </Border>
</UserControl>
查看更多
趁早两清
5楼-- · 2020-02-06 06:28

I sometimes have nested User controls and a grandchild usercontrol sometimes needs the grandparent's view's data context. The easiest way I have found so far (and I'm somewhat of a newbie) is to use the following:

<Shared:GranchildControl DataContext="{Binding RelativeSource={RelativeSource 
                    FindAncestor, AncestorType={x:Type GrandparentView}},
                    Path=DataContext.GrandparentViewModel}" />

I wrote up a more detailed example on my blog if you want more specifics.

查看更多
登录 后发表回答