Удаление дочернего элемента из панели, связанной с ItemsSource - PullRequest
0 голосов
/ 20 ноября 2018

Я пытаюсь создать функцию перетаскивания для пары кнопок, которые содержатся в ObservableCollection<> в модели представления, коллекция позже используется как ItemsSource для StackPanel:

Это структура xaml:

<ItemsControl x:Name="RingHolder" Grid.Column="0" Grid.ColumnSpan="3" ItemsSource="{Binding Rings}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <customControls:RingsStackpanel Orientation="Vertical" VerticalAlignment="Bottom"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <customControls:RingControl VerticalAlignment="Stretch" Height="50"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Где RingsStackPanel наследуется от StackPanel, а RingControl наследуется от Button.

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

if (VisualTreeHelper.GetParent(this) is ContentPresenter contentPresenter)
{
    if (VisualTreeHelper.GetParent(contentPresenter) is RingsStackpanel ringStackPanel)
    {
        ringStackPanel.Children.Remove(contentPresenter);
    }
}

Однако я получаю следующее исключение:

InvalidOperationException:

Не могуявно изменить коллекцию Children для Panel, которая используется как ItemsPanel для ItemsControl.ItemsControl генерирует дочерние элементы для Panel

. Это имеет смысл, я могу изменить его только путем изменения привязанного к нему ItemsSource, однако в этом сценарии удаление элемента из ObservableCollection<> вызываетвыбранный Button исчезает по мере его уничтожения.Могу ли я в любом случае позволить своему Button свободно перемещаться, не создавая его клона (это было бы почти невозможно, поскольку проект в настоящее время).

1 Ответ

0 голосов
/ 20 ноября 2018

Вы можете удалить элемент данных из исходной коллекции и добавить открытый метод к вашему классу RingsStackpanel, который удаляет визуал из логического дерева:

public class RingsStackpanel : StackPanel
{
    ...
    public void RemoveElement(Visual visual) => RemoveVisualChild(visual);
}

После этого вы сможете обрабатыватьUnloaded событие ContentPresenter и удалите его родитель-потомок с помощью StackPanel.Как то так:

if (VisualTreeHelper.GetParent(this) is ContentPresenter contentPresenter)
{
    if (VisualTreeHelper.GetParent(contentPresenter) is RingsStackpanel ringStackPanel
        && RingHolder.ItemsSource is ObservableCollection<YourItemType> dataItems
        && contentPresenter.DataContext is YourItemType dataItem)
    {
        //wait for the ContentPresenter to get unloaded
        RoutedEventHandler handler = null;
        handler = (ss, ee) =>
        {
            //remove the parent-child relationship:
            ringStackPanel.RemoveElement(contentPresenter);

            contentPresenter.Unloaded -= handler;
        };
        //remove the data object
        dataItems.Remove(dataItem);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...