Search code examples
c#wpfxamldatacontexticommand

My DataContext changed. How to properly perform Binding


I am working on UserControl where I have TreeView based on custom class, build like that:

-ConnectionModel

---SchemaModel

-----SchemaCollection

-------TableModel

TreeView is working like a charm.

I added ContextMenu after click on TableModel item in TreeView. Then I want to create binding to Command "SelectFromTab" which I declare in SideBar() class ( which is ModelView to this View ) .

How should I properly make Binding to SelectFromTab command in SideBar class? Now DataContext of ContextMenu is set to "TableModel".

My View ( full .xaml )

<Page
  ....
  xmlns:local="clr-namespace:ProgDB4.ViewModel"
  xmlns:models="clr-namespace:ProgDB4.Model"

  xmlns:ProgDB4="clr-namespace:ProgDB4" x:Name="page" x:Class="ProgDB4.ViewModel.SideBar"

  mc:Ignorable="d" 
  d:DesignHeight="300" d:DesignWidth="300"
  Title="SideBar">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition Height="20"/>
    </Grid.RowDefinitions>
    <TabControl Grid.Row="0" x:Name="SideBarTabControl" SelectionChanged="SideBarTabControl_SelectionChanged">
        <TabItem Header="Map" Content="Mapa"/>
        <TabItem Header="History" Content="History"/>
        <TabItem Header="Aliases" x:Name="tab_aliases"   Width="52">
            <Grid>
                <TreeView x:Name="AliasTree" ItemsSource="{Binding TVData}">
                    <TreeView.Resources >
                        <HierarchicalDataTemplate DataType="{x:Type models:ConnectionModel}"  ItemsSource="{Binding schemas}">
                            <TextBlock Text="{Binding alias}" />
                        </HierarchicalDataTemplate>

                        <HierarchicalDataTemplate DataType="{x:Type models:SchemaModel}"      ItemsSource="{Binding schema_collections}">
                            <TextBlock Text="{Binding SCHEMA_NAME}" />
                        </HierarchicalDataTemplate>


                        <HierarchicalDataTemplate DataType="{x:Type models:SchemaCollection}"  ItemsSource="{Binding collection}">
                            <TextBlock Text="{Binding SCHEMA_COLLECTION_NAME}" />
                        </HierarchicalDataTemplate>

                        <DataTemplate DataType="{x:Type models:TableModel}" >
                            <TextBlock Text="{Binding TABLE_NAME}" PreviewMouseRightButtonDown="TextBlock_PreviewMouseRightButtonDown" >

                                <TextBlock.ContextMenu>
                                    <ContextMenu>
                                        <MenuItem Header="SELECT TOP 100"  Command ="{Binding SelectFromTab}"/>
                                        <MenuItem Header="SELECT TOP 1000"/>
                                        <MenuItem Header="Display indexes"/>
                                        <MenuItem Header="Display columns"/>
                                    </ContextMenu>
                                </TextBlock.ContextMenu>

                            </TextBlock>
                        </DataTemplate>
                    </TreeView.Resources>
                </TreeView>

            </Grid>
        </TabItem>
    </TabControl>
    <TextBox x:Name="SearchBox" Text="Search..." Height="20" Grid.Row="1" TextChanged="SearchBox_TextChanged" GotFocus="SearchBox_GotFocus" LostFocus="SearchBox_LostFocus"/>
</Grid>

My SideBar class :

public partial class SideBar : Page, INotifyPropertyChanged
{
    private List<ConnectionModel> _TVData;
    public MainViewModel mainViewModelContext;
    public TreeView tmpAliasTree = new TreeView();

    public ICommand _SelectFromTab;
    public ICommand SelectFromTab
    {
        get
        {
            MessageBox.Show("ddd");
            return _SelectFromTab;

        }
        set { if (value != _SelectFromTab) { _SelectFromTab = value; } }
    }

    public SideBar( MainViewModel mainViewContext )
    {
        TreeViewBase = new List<ConnectionModel>(ConnectionUtilities.LoadObservableConnections());
        mainViewModelContext = mainViewContext ;

        InitializeComponent();

        this.DataContext = this  ;

        // this.SelectFromTab = mainViewModelContext.SelectFromTab  ;

        var loadSideBar = Task.Factory.StartNew(async () => { await LoadSideBar(); });
        loadSideBar.Wait();

        OnPropertyChanged("TVData");
    }

Solution

  • ContextMenu doesn't get same DataContext as your UserControl. You can set it manually.

    private void ContextMenu_Loaded(object sender, RoutedEventArgs e)
        {
            (sender as FrameworkElement).DataContext = this;
        }
    

    and your command will work fine.