Как связать MenuFlyout "itemsource" с коллекцией, когда на странице несколько всплывающих окон? - PullRequest
0 голосов
/ 25 апреля 2018

У меня есть сетка с выпадающим меню на каждом элементе сетки.Это усложняется тем фактом, что мне нужно привязать ItemsSource каждого выпадающего меню к коллекции.Поскольку menuflyout не имеет свойства ItemsSource по умолчанию, я попытался использовать решение Джерри Никсона, опубликованное здесь: Почему в Windows 8.1 MenuFlyout нет свойства ItemsSource?

Все работает нормальнопервый раз, когда я нажимаю на элемент сетки.Однако, когда я нажимаю на другой элемент gridview, я получаю следующую ошибку: «Элемент уже является дочерним элементом другого элемента».

Я предполагаю, что Visual Studio жалуется, потому что всплывающее меню уже прикреплено кпервый элемент сетки, когда я нажимаю на следующий, и он пытается повторно использовать шаблон данных.Кто-нибудь может помочь?

XAML:

<GridView 
            ItemsSource="{x:Bind ViewModel.SourceForOfferorsList}"
                IsItemClickEnabled="True"
                IsTapEnabled="True"
                IsSwipeEnabled="False"
                CanDragItems="False"
                SelectionMode="Single"
                >
        <GridView.ItemTemplate>
            <DataTemplate x:DataType="models:SetupCompany" >
                <Grid x:Name="MyGrid">
                    <FlyoutBase.AttachedFlyout>
                        <Flyout helpers:BindableFlyout.ItemsSource="{Binding ElementName=RankPage,Path=DataContext.SourceForSubfactorsFlyoutList,Mode=TwoWay}">
                            <helpers:BindableFlyout.ItemTemplate>
                                <DataTemplate>
                                    <MenuFlyoutItem Text="{Binding Text}" />
                                </DataTemplate>
                            </helpers:BindableFlyout.ItemTemplate>
                        </Flyout>
                    </FlyoutBase.AttachedFlyout>
                    <i:Interaction.Behaviors>
                        <core:EventTriggerBehavior EventName="Tapped">
                            <helpers:OpenFlyoutAction/>
                        </core:EventTriggerBehavior>

                    </i:Interaction.Behaviors>

                    <TextBlock Text="Hello"></TextBlock>
                </Grid>
            </DataTemplate>
        </GridView.ItemTemplate>
    </GridView>

Класс OpenFlyoutAction:

    public object Execute(object sender, object parameter)
    {
        try
        {
            FlyoutBase.ShowAttachedFlyout((FrameworkElement)sender);
        }
        catch (Exception e)
        {

            throw;
        }
        return null;
    }

Класс Bindable Flyout:

public class BindableFlyout : DependencyObject
{
    #region ItemsSource

    public static IEnumerable GetItemsSource(DependencyObject obj)
    {

        return obj.GetValue(ItemsSourceProperty) as IEnumerable;


    }
    public static void SetItemsSource(DependencyObject obj, IEnumerable value)
    {

        obj.SetValue(ItemsSourceProperty, value);

    }
    public static readonly DependencyProperty ItemsSourceProperty =
        DependencyProperty.RegisterAttached("ItemsSource", typeof(IEnumerable),
        typeof(BindableFlyout), new PropertyMetadata(null, ItemsSourceChanged));
    private static void ItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    { Setup(d as Windows.UI.Xaml.Controls.Flyout); }

    #endregion

    #region ItemTemplate

    public static DataTemplate GetItemTemplate(DependencyObject obj)
    {
        return (DataTemplate)obj.GetValue(ItemTemplateProperty);
    }
    public static void SetItemTemplate(DependencyObject obj, DataTemplate value)
    {
        obj.SetValue(ItemTemplateProperty, value);
    }
    public static readonly DependencyProperty ItemTemplateProperty =
        DependencyProperty.RegisterAttached("ItemTemplate", typeof(DataTemplate),
        typeof(BindableFlyout), new PropertyMetadata(null, ItemsTemplateChanged));
    private static void ItemsTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    { Setup(d as Windows.UI.Xaml.Controls.Flyout); }

    #endregion

    private static async void Setup(Windows.UI.Xaml.Controls.Flyout m)
    {
        if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)
            return;
        var s = GetItemsSource(m);
        if (s == null)
            return;
        var t = GetItemTemplate(m);
        if (t == null)
            return;
        var c = new Windows.UI.Xaml.Controls.ItemsControl
        {
            ItemsSource = s,
            ItemTemplate = t,
        };
        var n = Windows.UI.Core.CoreDispatcherPriority.Normal;
        Windows.UI.Core.DispatchedHandler h = () => m.Content = c;
        await m.Dispatcher.RunAsync(n, h);
    }
}

1 Ответ

0 голосов
/ 26 апреля 2018

Я изменил некоторые места в вашем коде и сделал простой пример кода для справки:

<GridView x:Name="gridview"
            IsItemClickEnabled="True"
            IsTapEnabled="True"
            IsSwipeEnabled="False"
            CanDragItems="False"
            SelectionMode="Single">
        <GridView.ItemTemplate>
            <DataTemplate >
                <Grid x:Name="MyGrid">
                    <FlyoutBase.AttachedFlyout>
                        <Flyout local:BindableFlyout.ItemsSource="{Binding menuItems}">
                            <local:BindableFlyout.ItemTemplate>
                                <DataTemplate>
                                    <MenuFlyoutItem Text="{Binding Text}" />
                                </DataTemplate>
                            </local:BindableFlyout.ItemTemplate>
                        </Flyout>
                    </FlyoutBase.AttachedFlyout>
                    <TextBlock Text="{Binding item}"></TextBlock>
                    <i:Interaction.Behaviors>
                        <core:EventTriggerBehavior EventName="RightTapped">
                            <core:InvokeCommandAction Command="{Binding relayCommand}" CommandParameter="{Binding ElementName=MyGrid}"/>
                        </core:EventTriggerBehavior>
                    </i:Interaction.Behaviors>
                </Grid>
            </DataTemplate>
        </GridView.ItemTemplate>
    </GridView>
public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        List<Test> ls = new List<Test>();
        List<MyMenuItem> myMenuItems = new List<MyMenuItem>();
        myMenuItems.Add(new MyMenuItem() {Text="menu1" });
        myMenuItems.Add(new MyMenuItem() {Text="menu2" });
        ls.Add(new Test() {item="item1",menuItems=myMenuItems });
        ls.Add(new Test() { item = "item2", menuItems = myMenuItems });
        gridview.ItemsSource = ls;
    }
}

public class Test:ViewModelBase
{
    public string item { get; set; }

    public List<MyMenuItem> menuItems { get; set; }

    public RelayCommand<object> relayCommand { get; set; }

    public Test()
    {
        relayCommand = new RelayCommand<object>(ShowFlyout);
    }

    private void ShowFlyout(object obj)
    {
        FrameworkElement senderElement = obj as FrameworkElement;
        FlyoutBase flyoutBase = FlyoutBase.GetAttachedFlyout(senderElement);
        flyoutBase.ShowAt(senderElement);
    }
}

public class MyMenuItem
{
    public string Text { get; set; }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...