Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/269.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将可观察到的集合彼此分开 信息_C#_Wpf_Observablecollection - Fatal编程技术网

C# 将可观察到的集合彼此分开 信息

C# 将可观察到的集合彼此分开 信息,c#,wpf,observablecollection,C#,Wpf,Observablecollection,我有两个相同的屏幕截图对象的observedcollection。一个称为Screenshots,其中包含用户可用的所有可能屏幕;另一个称为SelectedScreenshots,这是用户想要组合的选定屏幕。每次用户通过单击WPF中绑定到屏幕截图的列表来选择屏幕时,我都会在SelectedScreenshots中添加一个新屏幕 问题 问题是,当我刷新屏幕并清除Screenshots以便查看屏幕上更新的内容时,它也会清除SelectedScreenshots,即使它是不同的对象。我知道它们指向内存

我有两个相同的
屏幕截图
对象的
observedcollection
。一个称为
Screenshots
,其中包含用户可用的所有可能屏幕;另一个称为
SelectedScreenshots
,这是用户想要组合的选定屏幕。每次用户通过单击WPF中绑定到
屏幕截图的列表来选择屏幕时,我都会在
SelectedScreenshots
中添加一个新屏幕

问题 问题是,当我刷新屏幕并清除
Screenshots
以便查看屏幕上更新的内容时,它也会清除
SelectedScreenshots
,即使它是不同的对象。我知道它们指向内存中的同一个位置,但我该如何绕过它呢?深度复制是一种解决方案。还有别的选择吗

代码 特性:

public ObservableCollection<Screenshot> Screenshots { get; set; } = new ObservableCollection<Screenshot>();

public ObservableCollection<Screenshot> SelectedScreenshots { get; set; } = new ObservableCollection<Screenshot>();
截图类:

public class Screenshot : ViewModelBase
{
    private BitmapImage _screenImage;
    public BitmapImage ScreenImage
    {
        get { return _screenImage; }
        set
        {
            _screenImage = value;
            OnPropertyChanged();
        }
    }

    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            OnPropertyChanged();
        }
    }

    public Screenshot(BitmapImage screenImage, string name)
    {
        this.ScreenImage = screenImage;
        this.Name = name;
    }
}

正在清除SelectedScreenshots的是UI,因为您绑定到的控件只能包含items源中存在的选定项,并且每次刷新时您都会创建一组全新的屏幕截图

解决方案可能是在刷新之前将所选项目保存到另一个集合,然后在刷新之后重新选择,或者只是更新现有的屏幕截图集

我希望您希望在UI中保留选定的屏幕截图。为了实现这一点,您需要以某种方式将旧的屏幕截图实例链接到新的屏幕截图实例。希望你能用DeviceName做到这一点?还是按命令?这一点由你决定

private void InitScreens()
{
    var screenshots = Screen.AllScreens.OrderBy(scrn => scrn.Bounds.Location.X).ThenBy(scrn => scrn.Bounds.Location.Y).Select(screen => new Screenshot(GetScreenImage(screen.Bounds), screen.DeviceName));

    App.Current.Dispatcher.InvokeAsync(delegate
    {
        // store current selections
        var currentSelections = SelectedScreenshots.ToArray();

        Screenshots.Clear();

        for (int i = 0; i < 3; i++)
        {
            Screenshots.Add(screenshots.ElementAt(i));
        }

        // select what was previously selected
        SelectedScreenshots = new ObservableCollection<Screenshot>(Screenshots
           .Where(s => currentSelections.Any(c => c.DeviceName == s.DeviceName)));
    });
}
private void InitScreens()
{
var screenshots=Screen.AllScreens.OrderBy(scrn=>scrn.Bounds.Location.X)。然后by(scrn=>scrn.Bounds.Location.Y)。选择(Screen=>newscreenshot(GetScreenImage(Screen.Bounds)、Screen.DeviceName));
App.Current.Dispatcher.InvokeAsync(委托
{
//存储当前选择
var currentSelections=SelectedScreenshots.ToArray();
屏幕截图。清除();
对于(int i=0;i<3;i++)
{
屏幕截图.Add(屏幕截图.ElementAt(i));
}
//选择以前选择的内容
SelectedScreenshots=新的ObservableCollection(屏幕截图
。其中(s=>currentSelections.Any(c=>c.DeviceName==s.DeviceName));
});
}

正是UI在清除SelectedScreenshots,因为您绑定到的控件只能包含items源中存在的选定项,并且每次刷新时您都会创建一组全新的屏幕截图

解决方案可能是在刷新之前将所选项目保存到另一个集合,然后在刷新之后重新选择,或者只是更新现有的屏幕截图集

我希望您希望在UI中保留选定的屏幕截图。为了实现这一点,您需要以某种方式将旧的屏幕截图实例链接到新的屏幕截图实例。希望你能用DeviceName做到这一点?还是按命令?这一点由你决定

private void InitScreens()
{
    var screenshots = Screen.AllScreens.OrderBy(scrn => scrn.Bounds.Location.X).ThenBy(scrn => scrn.Bounds.Location.Y).Select(screen => new Screenshot(GetScreenImage(screen.Bounds), screen.DeviceName));

    App.Current.Dispatcher.InvokeAsync(delegate
    {
        // store current selections
        var currentSelections = SelectedScreenshots.ToArray();

        Screenshots.Clear();

        for (int i = 0; i < 3; i++)
        {
            Screenshots.Add(screenshots.ElementAt(i));
        }

        // select what was previously selected
        SelectedScreenshots = new ObservableCollection<Screenshot>(Screenshots
           .Where(s => currentSelections.Any(c => c.DeviceName == s.DeviceName)));
    });
}
private void InitScreens()
{
var screenshots=Screen.AllScreens.OrderBy(scrn=>scrn.Bounds.Location.X)。然后by(scrn=>scrn.Bounds.Location.Y)。选择(Screen=>newscreenshot(GetScreenImage(Screen.Bounds)、Screen.DeviceName));
App.Current.Dispatcher.InvokeAsync(委托
{
//存储当前选择
var currentSelections=SelectedScreenshots.ToArray();
屏幕截图。清除();
对于(int i=0;i<3;i++)
{
屏幕截图.Add(屏幕截图.ElementAt(i));
}
//选择以前选择的内容
SelectedScreenshots=新的ObservableCollection(屏幕截图
。其中(s=>currentSelections.Any(c=>c.DeviceName==s.DeviceName));
});
}

如果您的屏幕截图对象具有引用类型的属性,那么我认为您需要按照您所说的做;执行深度复制以确保Screenshots属性中的Screenshot对象和SelectedScreenshots属性中的Screenshot对象未指向相同的内存位置。在过去,我在对象中创建了一个PerformDeepCopy()方法,在您的例子中,它就是Screenshot对象。在此方法中,您可以执行MemberwiseClone(),这是一个浅拷贝。这将复制Screenshot类中的Name属性。然后,您将手动为引用类型分配一个新的内存地址。这是BitmapImage属性“更新”的位置。返回值是一个新的屏幕截图对象。例如:

public class Screenshot : ViewModelBase
{
    private BitmapImage _screenImage;
    public BitmapImage ScreenImage
    {
        get { return _screenImage; }
        set
        {
            _screenImage = value;
            OnPropertyChanged();
        }
    }

    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            OnPropertyChanged();
        }
    }

    public Screenshot(BitmapImage screenImage, string name)
    {
        this.ScreenImage = screenImage;
        this.Name = name;
    }

    public Screenshot PerformDeepCopy()
    {
        Screenshot deepCopy = (Screenshot)this.MemberwiseClone();
        deepCopy.ScreenImage = new BitmapImage(this.ScreenImage.UriSource);
        return deepCopy;
    }
}

如果你的屏幕截图对象的属性是引用类型,那么我认为你需要按照你说的去做;执行深度复制以确保Screenshots属性中的Screenshot对象和SelectedScreenshots属性中的Screenshot对象未指向相同的内存位置。在过去,我在对象中创建了一个PerformDeepCopy()方法,在您的例子中,它就是Screenshot对象。在此方法中,您可以执行MemberwiseClone(),这是一个浅拷贝。这将复制Screenshot类中的Name属性。然后,您将手动为引用类型分配一个新的内存地址。这是BitmapImage属性“更新”的位置。返回值是一个新的屏幕截图对象。例如:

public class Screenshot : ViewModelBase
{
    private BitmapImage _screenImage;
    public BitmapImage ScreenImage
    {
        get { return _screenImage; }
        set
        {
            _screenImage = value;
            OnPropertyChanged();
        }
    }

    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            OnPropertyChanged();
        }
    }

    public Screenshot(BitmapImage screenImage, string name)
    {
        this.ScreenImage = screenImage;
        this.Name = name;
    }

    public Screenshot PerformDeepCopy()
    {
        Screenshot deepCopy = (Screenshot)this.MemberwiseClone();
        deepCopy.ScreenImage = new BitmapImage(this.ScreenImage.UriSource);
        return deepCopy;
    }
}

值得注意的是,在初始化可观察集合以分离新对象时,它们实际上并不指向内存中的同一位置。列表中的项指向内存中的同一位置,但从集合中删除项并不会将其从内存中删除(至少不会立即删除),因此另一个列表仍保留屏幕截图对象值得注意的是,可观察的集合实际上没有指向内存中的同一位置,初始化它们以分离新对象时。列表中的项指向内存中的同一位置,但从集合中删除项并不会将其从内存中删除(在l