WPF: как установить свойство только для выбранного элемента, а не для источника элемента - PullRequest
1 голос
/ 13 апреля 2020

У меня есть просмотр списка с Combobox:

<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>

Согласно моим логам c RelatedDiscounts (на самом деле мой просмотр списка) - это список SelectedDiscounts. Я могу добавить скидку, и она будет установлена ​​как SelectedItem в моем Combobox (для этого я должен ovverride Equals в классе SelectedDiscount). Каждая скидка имеет свойство IsNotRelated (true / false в зависимости от логина c). Я столкнулся с проблемой: например, мой первый элемент списка SelectedDiscount был установлен как SelectedItem в первом Combobox, и его свойство IsNotRelated имеет значение false по логикам c. Затем я добавляю тот же элемент, что и SelectedItem, в свой второй Combobox, но свойство IsNotRelated имеет значение true. В этом случае первое свойство SelectedDiscount IsNotRelated также становится истинным, но должно оставаться ложным. Я знаю, это потому, что во второй раз я установил значение true для свойства SelectedDiscount из ItemSourse всех моих комбинированных списков. Мой вопрос: как я могу установить свойство только для SelectedItem текущего Combobox, но не для этого элемента в ItemSourse вообще? Любые идеи, как я могу избежать стандартного поведения Combobox и извините за мой Engli sh.

Вот часть типа 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);
        }

1 Ответ

1 голос
/ 14 апреля 2020

Приношу свои извинения, если я неправильно понимаю вашу проблему ...

Причина, по которой вы, скорее всего, это видите, заключается в том, что объект SelectedDiscount, к которому вы привязываете каждый ComboBox, является таким же изменяемым объект. Хотя объект указан в отдельных коллекциях, он является одним и тем же объектом в памяти. Коллекция просто содержит ссылку на 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, так как они не могут измениться. Каждая коллекция будет создавать свою собственную версию объекта, а не ссылку, как у mutable объекта.

По сути, вам потребуется создать новый экземпляр объекта 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 может не работать в зависимости от структуры класса. Я просто хотел привести вам пример, но теперь, когда вы знаете, ПОЧЕМУ он ведет себя так, как есть, вы можете решить эту проблему.

С наилучшими пожеланиями!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...