当 ObservableCollection 通过绑定更改时,自定义 UIElement 不会更新布局
Custom UIElement does not update layout when an ObservableCollection changes through binding
又遇到了一个(可能)简单的问题。
我想创建一个自定义 UIElement(一组保持正交的线)。
此 UIElement 在我的 MVVM 应用程序中用作视图。
这是我的代码:
class RaOrthogonalLine : Canvas, INotifyPropertyChanged
{
public RaOrthogonalLine()
{
Points.CollectionChanged += Points_CollectionChanged;
}
void Points_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
Paint();
}
void Paint()
{
//PaintingStuff! Here I would like to get in!
}
void newLine_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (LineClicked != null)
LineClicked(sender, e);
}
public delegate void LineClickedEventHandler(object sender, MouseButtonEventArgs e);
public event LineClickedEventHandler LineClicked;
public ObservableCollection<RaPoint> Points
{
get
{
return (ObservableCollection<RaPoint>)GetValue(PointsProperty);
}
set
{
SetValue(PointsProperty, value);
RaisePropertyChanged("Points");
}
}
public static readonly DependencyProperty PointsProperty = DependencyProperty.Register("Points", typeof(ObservableCollection<RaPoint>), typeof(RaOrthogonalLine),
new FrameworkPropertyMetadata(new ObservableCollection<RaPoint>(), new PropertyChangedCallback(PointsPropertyChanged))
{
BindsTwoWayByDefault = true,
DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
}
);
private static void PointsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
RaOrthogonalLine thisLine = (RaOrthogonalLine)d;
thisLine.Paint();
}
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
在我的 XAML 中,我将 ViewModel 的 ObservableCollection 绑定到 UIElement(View) 中的 ObservableCollection。
效果很好。
我现在的问题是当集合发生变化时我没有收到通知 (Add/Remove/..) - 因为那时我需要重新绘制它。
我尝试获取 Points.CollectionChanged 事件,但它没有触发。
有人有想法吗?
谢谢!
问题是您在控件的构造函数中添加了 CollectionChanged
事件处理程序。在构造函数中,您的 Paint 属性 尚未绑定到正确的源(实际上它具有 PointsProperty 的默认值,即空集合)。
您应该在 PointsPropertyChanged
方法中添加和删除事件处理程序。看看这个示例代码:
public class RaOrthogonalLine : Canvas
{
public INotifyCollectionChanged Points
{
get { return (INotifyCollectionChanged)GetValue(PointsProperty); }
set { SetValue(PointsProperty, value); }
}
public static readonly DependencyProperty PointsProperty =
DependencyProperty.Register("Points", typeof(INotifyCollectionChanged), typeof(RaOrthogonalLine),
new FrameworkPropertyMetadata(null, new PropertyChangedCallback(PointsPropertyChanged))
{
BindsTwoWayByDefault = true,
DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
});
void Points_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
Paint();
}
private static void PointsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
RaOrthogonalLine raOrthogonalLine = (RaOrthogonalLine)d;
INotifyCollectionChanged newValue = (INotifyCollectionChanged)e.NewValue;
INotifyCollectionChanged oldValue = (INotifyCollectionChanged)e.OldValue;
if (oldValue != null)
{
oldValue.CollectionChanged -= raOrthogonalLine.Points_CollectionChanged;
}
if (newValue != null)
{
newValue.CollectionChanged += raOrthogonalLine.Points_CollectionChanged;
}
raOrthogonalLine.Paint();
}
}
希望对您的问题有所帮助。
这可能与依赖性有关属性,但这对我来说很好用。
您确定要在集合中添加和删除(而不是替换集合)吗?
public class Points
{
void Strings_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
Debug.WriteLine("Strings_CollectionChanged");
}
private ObservableCollection<string> strings = new ObservableCollection<string>();
// I think you are better off with just a get
public ObservableCollection<string> Strings { get { return strings; } }
public Points()
{
Strings.CollectionChanged += new NotifyCollectionChangedEventHandler(Strings_CollectionChanged);
Strings.Add("new one");
Strings.Add("new two");
Strings.RemoveAt(0);
}
}
又遇到了一个(可能)简单的问题。
我想创建一个自定义 UIElement(一组保持正交的线)。 此 UIElement 在我的 MVVM 应用程序中用作视图。
这是我的代码:
class RaOrthogonalLine : Canvas, INotifyPropertyChanged
{
public RaOrthogonalLine()
{
Points.CollectionChanged += Points_CollectionChanged;
}
void Points_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
Paint();
}
void Paint()
{
//PaintingStuff! Here I would like to get in!
}
void newLine_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (LineClicked != null)
LineClicked(sender, e);
}
public delegate void LineClickedEventHandler(object sender, MouseButtonEventArgs e);
public event LineClickedEventHandler LineClicked;
public ObservableCollection<RaPoint> Points
{
get
{
return (ObservableCollection<RaPoint>)GetValue(PointsProperty);
}
set
{
SetValue(PointsProperty, value);
RaisePropertyChanged("Points");
}
}
public static readonly DependencyProperty PointsProperty = DependencyProperty.Register("Points", typeof(ObservableCollection<RaPoint>), typeof(RaOrthogonalLine),
new FrameworkPropertyMetadata(new ObservableCollection<RaPoint>(), new PropertyChangedCallback(PointsPropertyChanged))
{
BindsTwoWayByDefault = true,
DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
}
);
private static void PointsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
RaOrthogonalLine thisLine = (RaOrthogonalLine)d;
thisLine.Paint();
}
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
在我的 XAML 中,我将 ViewModel 的 ObservableCollection 绑定到 UIElement(View) 中的 ObservableCollection。
效果很好。
我现在的问题是当集合发生变化时我没有收到通知 (Add/Remove/..) - 因为那时我需要重新绘制它。
我尝试获取 Points.CollectionChanged 事件,但它没有触发。
有人有想法吗?
谢谢!
问题是您在控件的构造函数中添加了 CollectionChanged
事件处理程序。在构造函数中,您的 Paint 属性 尚未绑定到正确的源(实际上它具有 PointsProperty 的默认值,即空集合)。
您应该在 PointsPropertyChanged
方法中添加和删除事件处理程序。看看这个示例代码:
public class RaOrthogonalLine : Canvas
{
public INotifyCollectionChanged Points
{
get { return (INotifyCollectionChanged)GetValue(PointsProperty); }
set { SetValue(PointsProperty, value); }
}
public static readonly DependencyProperty PointsProperty =
DependencyProperty.Register("Points", typeof(INotifyCollectionChanged), typeof(RaOrthogonalLine),
new FrameworkPropertyMetadata(null, new PropertyChangedCallback(PointsPropertyChanged))
{
BindsTwoWayByDefault = true,
DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
});
void Points_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
Paint();
}
private static void PointsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
RaOrthogonalLine raOrthogonalLine = (RaOrthogonalLine)d;
INotifyCollectionChanged newValue = (INotifyCollectionChanged)e.NewValue;
INotifyCollectionChanged oldValue = (INotifyCollectionChanged)e.OldValue;
if (oldValue != null)
{
oldValue.CollectionChanged -= raOrthogonalLine.Points_CollectionChanged;
}
if (newValue != null)
{
newValue.CollectionChanged += raOrthogonalLine.Points_CollectionChanged;
}
raOrthogonalLine.Paint();
}
}
希望对您的问题有所帮助。
这可能与依赖性有关属性,但这对我来说很好用。
您确定要在集合中添加和删除(而不是替换集合)吗?
public class Points
{
void Strings_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
Debug.WriteLine("Strings_CollectionChanged");
}
private ObservableCollection<string> strings = new ObservableCollection<string>();
// I think you are better off with just a get
public ObservableCollection<string> Strings { get { return strings; } }
public Points()
{
Strings.CollectionChanged += new NotifyCollectionChangedEventHandler(Strings_CollectionChanged);
Strings.Add("new one");
Strings.Add("new two");
Strings.RemoveAt(0);
}
}