Sebastian
Sebastian

Reputation: 377

Passing SelectedItem of a TreeView UserControl to the calling Window

I've created a dialog (Window) in which I'm using a UserControl with a TreeView. Now I need the SelectedItem of the TreeView (the Getter) in my dialog/window.

I have tried it with a DependencyProperty, but if I set a BreakPoint to the SelectedItem property of the dialog, it doesn't trigger.


My Window:

<itemViewer:ItemViewerControl DataContext="{Binding ListOfWorldItems}" 
                              SelectedItem="{Binding SelectedWorldItem, Mode=TwoWay}"/>/>

with CodeBehind:

public WorldItem SelectedWorldItem
{
    get { return selectedWorldItem; }
    set
    {
        selectedWorldItem = value;
        NotifyPropertyChanged("SelectedWorldItem");
    }
}

My UserControl

<itemViewer:ItemViewerControl DataContext="{Binding ListOfWorldItems}" />

with CodeBehind:

<UserControl ... >
    <UserControl.Resources>
        ... 
    </UserControl.Resources>

    <Grid>
        <TreeView x:Name="WorldItemsTreeView" 
                  SelectedItemChanged="TreeView_SelectedItemChanged"
                  ItemsSource="{Binding}" />
    </Grid>

</UserControl>




public static readonly DependencyProperty SelectedItemProperty =
    DependencyProperty.Register("SelectedItem", typeof(WorldItem), typeof(ItemViewerControl), new UIPropertyMetadata(null));


public ItemViewerControl()
{
    InitializeComponent();
    DataContext = this;
}

public WorldItem SelectedItem
{
    get { return (WorldItem)GetValue(SelectedItemProperty); }
    set { SetValue(SelectedItemProperty, value); }
}

private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
    SelectedItem = (WorldItem)WorldItemsTreeView.SelectedItem;
}

Upvotes: 0

Views: 388

Answers (1)

Patrick B.
Patrick B.

Reputation: 69

The issue that you are running into is that you are setting the DataContext on your UserControl and then attempting to declare a binding. By default the binding will source its value from the DataContext of the element which contains the binding. In this case that is ListOfWorldItems, not the dialog. So the binding of the SelectedItem property on the UserControl actually fails (you can see this in the output window when debugging the application).

One way to resolve this is to explicitly set the source for the binding, instead of relying on the default behavior. If you change the line in your dialog to the following...

<itemViewer:ItemViewerControl DataContext="{Binding ListOfWorldItems}" 
                              SelectedItem="{Binding SelectedWorldItem, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=Window}"/>

It should now look to your dialog as the source for the binding and correctly establish binding between your UserControl and the dialog. Be careful that any other bindings you establish between your UserControl and the dialog also explicitly establish the source, otherwise they will run into the same problem you encountered here.

It doesn't look like it is contributing to the issue but as an additional note you are setting the DataContext for your UserControl twice. Once in the constructor for the UserControl you are self-referencing and then it is overwritten when setting the DataContext in the dialog. In this case it doesn't look like it is causing a problem (aside from some minor inefficiency), but it could have unexpected side-effects if you ever changed how the DataContext for the UserControl is being set in the dialog.

Upvotes: 1

Related Questions