WPF access information from the containing control

I have a UserControl (a) with a stacked pane that has its ItemSource set to a collection. Then the StackPanel contains a set of UserControl (b), which contains several buttons and a datagrid control. Is there a way from the code in UserControl (b) to access the properties in the code behind the parent UserControl (a).

Basically, when UserControl (a) is loaded into a window, a parameter is passed that asks if the form will be read-only or not. I would like to bind the visibility of buttons in Usercontrol (b) to the readonly property in the code-language of the parent UserControl (a).

0


a source to share


1 answer


Usually with WPF, I suggest you implement the Model-View-ViewModel pattern (see MSDN ).

With this template, you will create a ViewModel with all the data you want to bind. This will be set as the data context for (a) usercontrol. This control will then bind all of its controls to properties in the datacontext.

Child (b) usercontrol inherits this datacontext and therefore can bind its controls to the same properties as (a). This is because datacontexts are inherited through the logical (and visual) tree as long as they are not overridden.

So, for you, I would look at creating a ViewModel that contains a ReadOnly property. Then you can set this ViewModel as datacontext for (a) usercontrol. User control (b) because it is under the hierarchy (a) usercontrol inherits the same data file. This will allow you to bind the controls in (b) with the same properties as (a) as shown below.

<Button IsEnabled="{Binding ReadOnly}"
    Context="Click me!"
    Command="{Binding ClickMeCommand}" />

      

In order to set datacontext to the code of the code I am doing something like this constructor shown below.

public MyView(IMyViewModel viewModel)
{
    InitializeComponent();
    DataContext = viewModel;
}

      



MyView is a class that inherits from UserControl in your instance. You don't need to get the viewmodel the way I am, I am using Unity to embed the viewmodel in the views that are automatically generated, as I am using Prism, but you can just create it as a regular object and assign it to the datacontext.

Note that I also bind the command to the button using datacontext, as I usually expose them through the ViewModel, it's easy if you create a wrapper class that implements ICommand and proxies for the delegate. See the blog post DelegateCommand or see the DelegateCommand class in Prism if you're interested.

If for some reason you override the datacontext, which can happen when using the master / details view, where you change the datacontext of the view details section, which is the currently selected item in the list, then you can still access the parent datacontext. using relative source binding.

eg.

<ComboBox Grid.Row="1" Grid.Column="1" x:Name="Unit" IsReadOnly="True"
      ItemsSource="{Binding Path=DataContext.AvailableUnits, RelativeSource=
                   {RelativeSource Mode=FindAncestor,
                                   AncestorType={x:Type Window}}}"
      DisplayMemberPath="Name" SelectedItem="{Binding Unit}" />

      

Note that the ItemsSource binding uses a relative source to find the parent window and then binds to the datacontext property. I've also split the quoted ItemsSource binding across multiple lines for clarity here, but don't do it in your xaml, I'm not sure if it will work there (didn't try to see if markup extensions are whitespace tolerant).

+2


a source







All Articles