Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
252 views
in Technique[技术] by (71.8m points)

flyout - UWP: find parent from FlyoutMenuItem click handler

Using UWP, I have a ListView where each item contains, among other things, a Button. Tapping the button opens a MenuFlyout. Tapping one of the flyout options triggers a Click event.

In the event handler, how do I find the parent Button or, alternatively, the parent ListView item ?

Here's an extract of my XAML. Specifically, I want to find the "Note" element while in the the OnItemEdit handler.

<Page.Resources>
  <ResourceDictionary>

    <DataTemplate x:Key="NoteItemTemplate">
      <Grid>
        <Grid.ColumnDefinitions> ... </Grid.ColumnDefinitions>
        <TextBox Name="Note" />
        <Button>
          <Image Source="..." />
          <Button.Flyout>
            <MenuFlyout>
              <MenuFlyoutItem Text="Edit" Click="OnItemEdit" />
              <MenuFlyoutItem Text="Delete" Click="OnItemDelete" />
            </MenuFlyout>
          </Button.Flyout>
        </Button>

      </Grid>
    </DataTemplate>
    ...
    <local:DetailItemSelector x:Key="DetailItemSelector"
      NoteItemTemplate="{StaticResource NoteItemTemplate}"
      ...
    />

  </ResourceDictionary>
</Page.Resources>

<ListView
  x:Name = "DetailList"
  ItemsSource = "{x:Bind DetailListItems}"
  ItemTemplateSelector = "{StaticResource DetailItemSelector}">
</ListView>

The handler is defined as:

async void OnItemEdit(object sender, RoutedEventArgs e)
{
  ...
}

EDIT - work around

If there's no better way, here's a work around that is not too bad. The trick is to use FlyoutBase.AttachedFlyout instead of Button.Flyout.

    <DataTemplate x:Key="NoteItemTemplate">
      <Grid>
        <Grid.ColumnDefinitions> ... </Grid.ColumnDefinitions>

        <TextBox ... Name="Note" />

        <Button ... Click=="onMoreClicked">
          <Image Source="..." />
          FlyoutBase.AttachedFlyout
            <MenuFlyout>
              <MenuFlyoutItem Text="Edit" Click="OnItemEdit" />
              <MenuFlyoutItem ... />
            </MenuFlyout>
          </FlyoutBase.AttachedFlyout>
        </Button>

      </Grid>
    </DataTemplate>

And, code behind

FrameworkElement lastItemTapped = null;

public void onMoreClicked (object sender, RoutedEventArgs e)
{
  Button button = sender as Button;

  // find parent list item containing button
  DependencyObject element = button;
  while (element != null)
  {
    if (element is FrameworkElement && (element as FrameworkElement).Name.Equals("Item"))
      break;
    element = VisualTreeHelper.GetParent(element);
  }
  if (element != null)
    lastItemTapped = element as FrameworkElement;

  // show flyout menu
  FlyoutBase.ShowAttachedFlyout(button);
}

public void OnItemEdit(object sender, RoutedEventArgs e)
{
  if (lastItemTapped == null)
    return;
  ...
}
question from:https://stackoverflow.com/questions/66052268/uwp-find-parent-from-flyoutmenuitem-click-handler

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Specifically, I want to find the "Note" element while in the the OnItemEdit handler.

Assuming the DataTemplate is applied to a "Note", that should be as easy as casting the DataContext of the sender argument to a Note (or whatever your type is called):

private void OnItemEdit(object sender, RoutedEventArgs e)
{
    MenuFlyoutItem menuFlyoutItem = (MenuFlyoutItem)sender;
    var note = menuFlyoutItem.DataContext as YourNoteClass;
    ...
}

If you need a reference to the "Node" TextBox element, you can find it in the visual tree:

private void OnItemEdit(object sender, RoutedEventArgs e)
{
    MenuFlyoutItem menuFlyoutItem = (MenuFlyoutItem)sender;
    DependencyObject container = DetailList.ContainerFromItem(menuFlyoutItem.DataContext);
    TextBox note = FindVisualChild<TextBox>(container);
    ...
}

private static T FindVisualChild<T>(DependencyObject visual) where T : DependencyObject
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(visual, i);
        if (child != null)
        {
            T correctlyTyped = child as T;
            if (correctlyTyped != null)
                return correctlyTyped;

            T descendent = FindVisualChild<T>(child);
            if (descendent != null)
                return descendent;
        }
    }
    return null;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...