Я довольно новичок в мире WPF / Binding, но теперь я использую его в течение некоторого времени с некоторой степенью успеха.
Теперь я застрял с проблемой, очень похожей на однуописанный в этот вопрос , но относительно класса вместо IEnumerable.Я не уверен, является ли поведение преднамеренным также для класса или если есть способ его решить.
Допустим, у меня есть свой простой пользовательский класс "Vector3", который содержит 3 двойника Vector3.cs
public class Vector3
{
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
public Vector3(double x, double y, double z)
{
X = x;
Y = y;
Z = z;
}
public Vector3(Vector3 vec)
{
X = vec.X;
Y = vec.Y;
Z = vec.Z;
}
public override bool Equals(object obj)
{
if (!(obj is Vector3))
return false;
Vector3 other = obj as Vector3;
return X == other.X && Y == other.Y && Z == other.Z;
}
public override int GetHashCode()
{
unchecked
{
return (X.GetHashCode() * 42) ^ Y.GetHashCode() + Z.GetHashCode();
}
}
}
И у меня есть пользовательский элемент управления, который предоставляет свойство DependencyProperty этого типа
ucVector3.xaml.cs
public partial class ucVector3 : UserControl
{
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value",
typeof(Vector3), typeof(ucVector3),
new FrameworkPropertyMetadata(null, new PropertyChangedCallback(_OnModelChanged)));
private static void _OnModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Console.WriteLine("Binding worked! I've received a new Vector3 " +
"with value X = " + (e.NewValue as Vector3).X);
}
public Vector3 Value
{
get
{
return (Vector3)GetValue(ValueProperty);
}
set
{
SetValue(ValueProperty, value);
}
}
...
Затем я пытаюсь использовать этот пользовательский элемент управленияпривязка свойства Value, как в этом примере:
MainWindow.xaml
<Window x:Class="StackOverflow.Example.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:StackOverflow.Example"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid Background="Azure">
<Grid.RowDefinitions>
<RowDefinition Height="5*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Content="Update" Margin="5" Grid.Row="1" Grid.ColumnSpan="2" Click="Button_Click" />
<local:ucVector3 Value="{Binding SameReference}" Margin="5" />
<local:ucVector3 Value="{Binding NewReference}" Margin="5" Grid.Column="1" />
</Grid>
</Window>
MainWindow.xaml.cs
public partial class MainWindow : Window, INotifyPropertyChanged
{
#region INotifyPropertyChanged
SynchronizationContext uiContext = SynchronizationContext.Current;
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
if (uiContext != SynchronizationContext.Current)
{
uiContext.Send(_ =>
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}, null);
}
else
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
private Vector3 newValue = new Vector3(0, 0, 0);
public Vector3 SameReference { get; set; }
public Vector3 NewReference { get; set; }
public MainWindow()
{
this.DataContext = this;
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
newValue.X = newValue.X + 2;
newValue.Y = newValue.Y + 3;
newValue.Z = newValue.Z + 4;
SameReference = newValue;
NewReference = new Vector3(newValue);
OnPropertyChanged("SameReference"); //successful notify, ignored values
OnPropertyChanged("NewReference"); //successful notify, processed values
}
}
При первом нажатии кнопки оба пользователяэлементы управления будут обновлены с помощью (3,4,5), но со второго раза будет обновлено только свойство «NewReference» в правом пользовательском элементе управления.
Я получаю, что для IEnumerables WPF будет распространятьСобытие OnPropertyChanged, только если ссылка отличается, и изменения в IEnumerable должны вызывать событие INotifyCollectionChanged.
Почему мой "OnPropertyChanged (" SameReference ")" "не распространяется?Я изменил значения, хочу, чтобы событие распространялось, чтобы обновить интерфейс, или я не назвал бы событие ...
Это поведение является преднамеренным?Почему он проверяет ссылку на объект, а не может быть, если он равен?Есть ли способ «заставить» событие пройти?Или как мне организовать свои занятия в этом случае?
Здесь вы можете скачать пример решения, описанного в этом вопросе , созданный в VisualStudio2015.
Спасибо всем за вашевремя.