Определить объект привязки, который вызывает контекстное меню в контейнере WPF? - PullRequest
0 голосов
/ 06 марта 2019

(весь этот запрос основан на предположении, что я могу создать контекстное меню в отдельном файле и прикрепить его к разным контейнерам в разных элементах управления - это предположение следует проверить)

Как определитьобъект привязки в элементе контейнера, который вызывает действие контекстного меню?

Я могу увидеть, как это сделать, посмотрев на SelectedItem объекта ListView, но я предпочитаю не знать о конкретном экземпляре ListView, например, чтобы одно и то же контекстное меню можно было присоединить к разным спискам.

Существует ли универсальное решение для определения объекта привязки, даже в разных типах контейнеров (например, необязательно ListView)?

<UserControl ...>

    <UserControl.Resources>
        <ContextMenu x:Key="ContextMenu">
            <MenuItem Header="Caption" Click="MenuItem_Click"></MenuItem>
        </ContextMenu>
    </UserControl.Resources>

    <ListView x:Name="ListView">
        <ListView.ContextMenu>
            <StaticResource ResourceKey="ContextMenu" />
        </ListView.ContextMenu>
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
            </GridView>
        </ListView.View>
    </ListView>

</UserControl>

Учитывая приведенный выше элемент управления, как добраться до объекта привязки для элемента, который был нажат?Я тону в супе свойств в RoutedEventArgs.

private void MenuItem_Click(object sender, RoutedEventArgs e)
{
  var obj = ??? as MyObjType;
  var name = obj.Name;
}

Кажется, это работает, как ожидалось, но жестко закодировано в экземпляр контейнера:

private void MenuItem_Click(object sender, RoutedEventArgs e)
{
    var obj = (MyObjType)NodesList.SelectedItem;
    MessageBox.Show(obj.Name);
}

Ответы [ 2 ]

0 голосов
/ 06 марта 2019

Если вы примените ContextMenu к отдельному элементу вместо того, чтобы применить его к самому ItemsControl ...:

<UserControl.Resources>
    <ContextMenu x:Key="ContextMenu">
        <MenuItem Header="Caption" Click="MenuItem_Click"></MenuItem>
    </ContextMenu>
</UserControl.Resources>

<ListView x:Name="ListView">
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="ContextMenu" Value="{StaticResource ContextMenu}" />
        </Style>
    </ListView.ItemContainerStyle>
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
        </GridView>
    </ListView.View>
</ListView>

... вы можете получить ссылку на элемент данных черезPlacementTarget из ContextMenu.Затем вы можете привести его к FrameworkElement, чтобы получить доступ к DataContext:

private void MenuItem_Click(object sender, RoutedEventArgs e)
{
    MenuItem mi = (MenuItem)sender;
    ContextMenu cm = mi.Parent as ContextMenu;
    if (cm != null)
    {
        FrameworkElement fe = cm.PlacementTarget as FrameworkElement;
        if (fe != null)
        {
            object dataItem = fe.DataContext;
            //...
        }
    }
}
0 голосов
/ 06 марта 2019

Если вы хотите использовать обобщенное приложение, попробуйте просто получить управление с помощью координат мыши. Вам нужно будет получить их, когда откроется меню:

<ContextMenu x:Key="ContextMenu" Opened="ContextMenu_Opened">
   <MenuItem Header="Caption" Click="MenuItem_Click" />
</ContextMenu>

Затем используйте при окончательном нажатии на элемент

private void ContextMenu_Opened(object sender, RoutedEventArgs e)
{
   var p = Mouse.GetPosition(this);
   var element = this.InputHitTest(p) as FrameworkElement;

   if (element != null)
   {
      //your data object
      ((ContextMenu)sender).DataContext = element.DataContext;
   }
}

private void MenuItem_Click(object sender, RoutedEventArgs e)
{
   var boundObject = ((MenuItem)sender).DataContext;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...