Reputation: 352
I have a WPF Window
and UserControl
which I use inside the Window
Window:
<Window x:Class="AdjacentControlVisualTree.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:AdjacentControlVisualTree"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<StackPanel Orientation="Vertical">
<local:AdjacentControl x:Name="AdjacentControl"/>
<Button Content="Foo"
CommandParameter="{Binding SelectedItem, ElementName=AdjacentControl.BarDataGrid}"
Command="{Binding FooCommand}"/>
</StackPanel>
</Window>
UserControl:
<UserControl x:Class="AdjacentControlVisualTree.AdjacentControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:AdjacentControlVisualTree">
<UserControl.DataContext>
<local:AdjacentViewModel/>
</UserControl.DataContext>
<Grid>
<DataGrid x:Name="BarDataGrid"
ItemsSource="{Binding Collection}"
IsReadOnly="True"
AutoGenerateColumns="False"
SelectionUnit="FullRow"
SelectionMode="Single">
<DataGrid.Columns>
<DataGridTextColumn Header="String" Binding="{Binding}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</UserControl>
Now, the thing is, that I would like to pass SelectedItem
property of DataGrid
inside the AdjacentControl to the FooCommand command but the binding always passes null:
CommandParameter="{Binding SelectedItem, ElementName=AdjacentControl.BarDataGrid}"
Is there a way how to make the binding work without having to change the structure of the controls?
Upvotes: 0
Views: 612
Reputation: 128060
The probably most simply way would be to expose BarDataGrid
as a property.
Change the XAML name (e.g. to x:Name="barDataGrid"
) and add this property to the UserControl's code behind:
public DataGrid BarDataGrid { get { return barDataGrid; } }
Then bind to the DataGrid's SelectedItem property like this:
CommandParameter="{Binding BarDataGrid.SelectedItem, ElementName=AdjacentControl}"
A cleaner solution would be not to expose the DataGrid child, but only its SelectedItem, by means of a dedicated dependency property.
public static readonly DependencyProperty SelectedItemProperty =
System.Windows.Controls.Primitives.Selector.SelectedItemProperty.AddOwner(
typeof(AdjacentControl));
public object SelectedItem
{
get { return GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
You would bind the DataGrid's SelectedItem to this property by a RelativeSource Binding
<DataGrid SelectedItem="{Binding SelectedItem,
RelativeSource={RelativeSource AncestorType=UserControl}}"
and bind the CommandParameter like this:
CommandParameter="{Binding SelectedItem, ElementName=AdjacentControl}"
Upvotes: 2