问题从可观察集合中删除对象

时间:2014-11-17 12:38:57

标签: c# wpf mvvm-light observablecollection

我有一个ItemsControl,它有一个Canvas作为ItemsPanelTemplate,一个椭圆作为ItemTemplate。我想要做的是当我拖动一个现有的Ellipse时,我希望它从我的可观察的EllipseXY对象集合中删除,这意味着它也将从我的Canvas中删除。我的拖动事件传递一个EllipseXY对象,然后可以在Drop事件中进行比较。但是当我删除我的集合中的EllipseXY对象时,尽管触发了Remove,但它仍会显示在我的画布上。可能的原因是什么?

型号:

public class EllipseXY
{
    public double X { get; set; }
    public double Y { get; set; }
    public Ellipse EllipseObject { get; set; }
}

视图模型:

private ObservableCollection<EllipseXY> ellipses;
    public ObservableCollection<EllipseXY> Ellipses
    {
        get { return ellipses; }
        set
        {
            if (ellipses == null)
            {
                ellipses = new ObservableCollection<EllipseXY>();
                ellipses = value;
            }
            else
            {
                ellipses = value;

            }
RaisePropertyChanged("Ellipses");
        }
    }

 #region EllipseXY
    public EllipseXY EllipseXY
    {
        get { return ellipsexy; }
        set
        {
            ellipsexy = value;
            RaisePropertyChanged("EllipseXY");
        }
    }

    public Ellipse EllipseObject
    {
        get { return ellipsexy.EllipseObject; }
        set
        {
            ellipsexy.EllipseObject = value;
            RaisePropertyChanged("EllipseObject");
        }
    }

    public double X
    {
        get { return ellipsexy.X; }
        set
        {
            ellipsexy.X = value;
            RaisePropertyChanged("X");
        }
    }

    public double Y
    {
        get { return ellipsexy.Y; }
        set
        {
            ellipsexy.Y = value;
            RaisePropertyChanged("Y");
        }
    }
    #endregion

拖动:

DataObject dragObject= new DataObject("dragObject", elliXY);
DragDrop.DoDragDrop(dragEllipse, dragObject, DragDropEffects.Move);

删除(不是所有代码,而是与此问题唯一相关的代码):

Model.EllipseXY ellipseXY = (Model.EllipseXY)e.Data.GetData("dragObject");
Ellipses.Remove(ellipseXY);

我也尝试过使用LINQ:

        EllipseXY test = (EllipseXY)Ellipses.Where(ellipse => ellipse.EllipseObject.Fill == dropEllipse.Fill);
        Ellipses.Remove(test);

但没有成功:P

编辑XAML:

 <ItemsControl ItemsSource="{Binding Ellipses}" DockPanel.Dock="Top">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas Name="CanvasDrop" Margin="10,0,10,0" Width="500" Height="400"
                            ClipToBounds="True" Background="{Binding Image}" AllowDrop="True" IsItemsHost="True">
                        <i:Interaction.Triggers>
                            <i:EventTrigger EventName="MouseMove">
                                <gala:EventToCommand Command="{Binding DragCommand}" PassEventArgsToCommand="True" />
                            </i:EventTrigger>
                            <i:EventTrigger EventName="Drop">
                                <gala:EventToCommand Command="{Binding DropCommand}" PassEventArgsToCommand="True" />
                            </i:EventTrigger>
                        </i:Interaction.Triggers>
                    </Canvas>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemContainerStyle>
                <Style TargetType="ContentPresenter">
                    <Setter Property="Canvas.Left" Value="{Binding Path=X}"/>
                    <Setter Property="Canvas.Top" Value="{Binding Path=Y}"/>
                </Style>
            </ItemsControl.ItemContainerStyle>
            <ItemsControl.ItemTemplate>
                <DataTemplate DataType="Ellipse">
                    <Ellipse Fill="{Binding EllipseObject.Fill}" Style="{StaticResource ellipseStyle}" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

2 个答案:

答案 0 :(得分:2)

您传递给Remove的项目需要与实例相同,而不仅仅是具有相同值的对象。

我怀疑目前情况并非如此,因为基于商品属性的过滤器可以解决问题,如评论中所述:

EllipseXY test = (EllipseXY)Ellipses.First(ellipse => ellipse.EllipseObject.Fill == dropEllipse.Fill);
Ellipses.Remove(test);

像这样,test引用列表中的实际实例,它符合过滤器表达式。

您可以进一步缩小选择范围,方法是创建更复杂的布尔表达式((ellipse.EllipseObject.Fill == dropEllipse.Fill) && (ellipse ...),或者在调用First之前插入多次调用Where,每个标准。

答案 1 :(得分:1)

这只是奇怪的 如果省略号为null,则忽略该值,不要调用RaisePropertyChanged。

public ObservableCollection<EllipseXY> Ellipses
{
    get { return ellipses; }
    set
    {
        if (ellipses == null) ellipses = new ObservableCollection<EllipseXY>();
        else
        {
            ellipses = value;
            RaisePropertyChanged("Ellipses");
        }
    }
}

这里有一个与房产相同的Notify

public EllipseXY EllipseXY
{
    get { return ellipsexy; }
    set
    {
        ellipsexy = value;
        RaisePropertyChanged("Ellipse");
    }
}

什么是llipses?

您的代码没有变得更好

private ObservableCollection<EllipseXY> ellipses;
public ObservableCollection<EllipseXY> Ellipses
{
    get { return ellipses; }
    set
    {
        if (ellipses == null)
        {
            ellipses = new ObservableCollection<EllipseXY>();
            ellipses = value;
        }
        else
        {
            ellipses = value;
            RaisePropertyChanged("Ellipses");
        }
    }
}

为什么要设置省略号= new ObservableCollection();然后立即设置省略号=值;
为什么RaisePropertyChanged(&#34; Ellipses&#34;);在别的?

试试这个

private ObservableCollection<EllipseXY> ellipses = new ObservableCollection<EllipseXY>();
public ObservableCollection<EllipseXY> Ellipses
{
    get { return ellipses; }
    set
    {
        if (ellipses == value) return; 
        ellipses = value;
        RaisePropertyChanged("Ellipses");
    }
}

添加Mapper的答案
这条线可能会破坏它

DataObject dragObject= new DataObject("dragObject", elliXY);

您正在创建一个新对象
另一种解决方案是在EllipseXY中重写GetHashCode和Equals