WPF:如何仅在selecteditem上设置属性,而不为项源设置属性



我有一个包含组合框的列表视图:

<ListView x:Name="DiscountListView" Grid.Row="1"
ItemsSource="{Binding DiscountMatrix.RelatedDiscounts}"
Margin="0, 7, 0, 0"
Style="{StaticResource AppTransparentListViewStyle}">
<ListView.View>
<GridView>
<GridViewColumn
Width="{Binding  RelativeSource={RelativeSource Mode=FindAncestor , AncestorType=ListView, AncestorLevel=1},Path=ActualWidth}">
<GridViewColumn.CellTemplate>
<ItemContainerTemplate>
<Grid HorizontalAlignment="Stretch" Margin="-7, 14, 0, 0"
Width="{Binding  RelativeSource={RelativeSource Mode=FindAncestor , AncestorType=ListViewItem, AncestorLevel=1},Path=ActualWidth}">
<Border BorderBrush ="{Binding SelectedDiscount.IsNotRelated, Converter={StaticResource DisablingBoolToColorConverter}}"  BorderThickness="2" Margin="4, 0, 15, 0">
<customComboBox:CustomComboBox x:Name="DiscountView" DisplayMemberPath="Name"
     Margin="0, 8, 5, 0"
     Text="{Binding SelectedDiscount.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
     SelectedValue ="{Binding SelectedDiscount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<customComboBox:CustomComboBox.ItemsSource>
<CompositeCollection>
<ComboBoxItem
Content="{DynamicResource lang_Common_SelectItem}"
IsEnabled="False" />
<CollectionContainer 
Collection="{Binding Source={StaticResource Discounts}}" />
</CompositeCollection>
</customComboBox:CustomComboBox.ItemsSource>
</customComboBox:CustomComboBox>
</Border>
</Grid>
</ItemContainerTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>

根据我的逻辑RelatedDiscounts(实际上是我的列表视图(是SelectedDiscounts的列表。我可以添加折扣,它将在我的组合框中设置为SelectedItem(为此,我应该在SelectedDiscount类中重写Equals(。每个折扣都具有IsNotRelated属性(true/false取决于逻辑(。我遇到了一个问题:例如,我的第一个列表项SelectedDiscount在第一个组合框中被设置为SelectedItem,并且它的IsNotRelated属性在逻辑上是false。然后,我将与SelectedItem相同的项添加到第二个组合框中,但IsNotRelated属性为true。在这种情况下,SelectedDiscount的属性IsNotRelated也变为true,但应保持为false。我知道这是因为我第二次将所有组合框的ItemSourse中的SelectedDiscount属性设置为true。我的问题是:如何只为当前组合框的SelectedItem设置属性,而不为ItemSourse中的此项设置属性?有什么想法我可以避免Combobox的标准行为,并为我的英语感到抱歉。

以下是SelectedDiscount类型(DiscountModel(的一部分:

public bool _isNotRelated;
[JsonIgnore]
public bool IsNotRelated
{
get { return _isNotRelated; }
set
{
_isNotRelated = value;
RaisePropertyChangedEvent("IsNotRelated");
}
}
public override bool Equals(object obj)
{
var other = obj as DiscountModel;
return (Id == other?.Id);
}

如果我误解了你的问题,我很抱歉。。。

您最有可能看到这种情况的原因是,您将每个ComboBox绑定到的对象SelectedDiscount是相同的可变对象。尽管对象列在不同的集合中,但它在内存中是同一个对象。该集合只是保存对内存中SelectedDiscount对象的引用,而不是对象本身。

例如:

var list1 = new List<SelectedDiscount>();
var list2 = new List<SelectedDiscount>();
SelectedDiscount sd = new SelectedDiscount();
list1.Add(sd);
list2.Add(sd);
//Change Collection 1
list1[0].IsNotRelated = true;
//Both collections return true
Console.WriteLine(list1[0].IsNotRelated); //True;
Console.WriteLine(list2[0].IsNotRelated); //True;

您不会看到这个问题不可变的对象,如string,因为它们无法更改。每个集合都将构建自己版本的对象,而不是像可变对象那样的引用。

本质上,您需要在内存中创建一个SelectedDiscount对象的新实例来修改其中一个,而不修改另一个。

一种方法是在类中实现ICloneable

public class SelectedDiscount : ICloneable
{
[JsonIgnore]
public bool IsNotRelated
{
get { return _isNotRelated; }
set
{
_isNotRelated = value;
RaisePropertyChangedEvent("IsNotRelated");
}
}
public object Clone()
{
return this.MemberwiseClone();
}
}

现在,您可以将对象克隆到新集合中。

var list1 = new List<SelectedDiscount>();
var list2 = new List<SelectedDiscount>();
//Assuming the IsNotRelated property is defaulted to false.
SelectedDiscount sd = new SelectedDiscount();
list1.Add(sd);
list2.Add((SelectedDiscount)sd.Clone());
//Change Collection 1
list1[0].IsNotRelated = true;
//Only the first collection will return true
Console.WriteLine(list1[0].IsNotRelated); //True;
Console.WriteLine(list2[0].IsNotRelated); //False;

您也可以实现自己的克隆方法,因为有时ICloneable可能不起作用,这取决于类结构。我只是想给你举个例子,但现在你知道了它为什么会这样,你就可以解决这个问题了。

祝福!

最新更新