Son*_*oul 10 .net c# wpf dependency-properties propertychanged
我有一个用户控件,它公开一个名为VisibileItems的DependencyProperty每次该属性更新时,我需要触发另一个事件.为此,我添加了一个带有PropertyChangedCallback事件的FrameworkPropertyMetadata.
出于某种原因,此事件仅被调用一次,并且在下次VisibleItems更改时不会触发.
XAML:
<cc:MyFilterList VisibleItems="{Binding CurrentTables}" />
Run Code Online (Sandbox Code Playgroud)
CurrentTables是MyViewModel上的DependencyProperty.CurrentTables经常变化.我可以将另一个WPF控件绑定到CurrentTables,我看到了UI中的更改.
这是我使用PropertyChangedCallback连接VisibleItems的方式
public static readonly DependencyProperty VisibleItemsProperty =
DependencyProperty.Register(
"VisibleItems",
typeof(IList),
typeof(MyFilterList),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(VisiblePropertyChanged))
);
public IList VisibleItems {
get { return (IList)GetValue(VisibleItemsProperty); }
set { SetValue(VisibleItemsProperty, value); }
}
Run Code Online (Sandbox Code Playgroud)
通过单步进入VisiblePropertyChanged,我可以看到第一次设置CurrentTables时会触发它.但不是后来的时间.
UPDATE
有些人质疑CurrentTables的修改方式,它会在更改时完全重新分配:
OnDBChange()...
CurrentTables = new List<string>(MainDatabaseDataAdapter.GetTables(this.SelectedServer, this.SelectedDatabase));
Run Code Online (Sandbox Code Playgroud)
每次更改时都会调用此行,但我的VisiblePropertyChanged处理程序仅在第一次调用时才会被调用.
UPDATE
如果我直接分配VisibleItems,每次都会调用处理程序!
TestFilterList.VisibleItems = new List<string>( Enumerable.Range(1, DateTime.Now.Second).ToList().Select(s => s.ToString()).ToList() );
Run Code Online (Sandbox Code Playgroud)
因此,它看起来像这个问题从的DependencyProperty(VisibleItems)茎看其他的DependencyProperty(CurrentTables).不知何故,绑定适用于第一次属性更改,但不适用于后续属性?正如你们中的一些人所建议的,试图用snoop检查这个问题.
Luk*_*ard 14
您是否将"本地"值(即直接分配给依赖项属性setter)设置为也具有OneWay
绑定的依赖项属性?如果是这样,设置本地值将删除绑定,如MSDN依赖项属性概述中所述:
绑定被视为本地值,这意味着如果您设置另一个本地值,您将消除绑定.
当要求在依赖项属性上存储本地值时,依赖项属性机制没有太多其他功能.它不能通过绑定发送值,因为绑定'指向'错误的方式.设置为本地值后,它不再显示从绑定中获得的值.由于它不再显示绑定的值,因此会删除绑定.
一旦绑定消失,PropertyChangedCallback
当绑定的source属性更改其值时,将不再调用will.这可能就是没有调用回调的原因.
如果将绑定设置为TwoWay
,绑定系统确实有一个地方存储您设置的"本地"值:在绑定的source属性中.在这种情况下,不需要消除绑定,因为依赖项属性机制可以将值存储在source属性中.
这种情况不会导致堆栈溢出,因为发生以下情况:
PropertyChanged
,PropertyChanged
事件,检查源属性的新值,发现它没有更改,并且不做任何进一步的操作.这里的关键点是,如果PropertyChanged
为值未更改的属性触发事件,PropertyChangedCallback
则不会调用绑定到您的属性的任何依赖项属性.
为简单起见,我IValueConverter
在上面忽略了s.如果您有转换器,请确保它正确地在两个方向上转换值.我还假设另一端的属性是实现对象的视图模型属性INotifyPropertyChanged
.在绑定的源端可能有另一个依赖属性.依赖属性机制也可以处理它.
碰巧,WPF(和Silverlight)不包含堆栈溢出检测.如果在a中PropertyChangedCallback
,您将依赖项属性的值设置为与其新值不同(例如,通过递增整数值属性或将字符串附加到字符串值属性),您将获得堆栈溢出.
小智 5
我的代码中有同样的问题,Luke是对的.我在PropertyChangedCallback中通过mystake调用了SetValue,导致潜在的无限循环.WPF防止这种静默禁用回调!!
我的WPF UserControl是
PatchRenderer
Run Code Online (Sandbox Code Playgroud)
我的C#属性是注意:
[Description("Note displayed with star icons"),
Category("Data"),
Browsable(true),
EditorBrowsable(EditorBrowsableState.Always),
DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int Note
{
get { return (int)GetValue(NoteProperty); }
set { SetValue(NoteProperty, value); /* don't put anything more here */ }
}
Run Code Online (Sandbox Code Playgroud)
我的WPF属性
public static readonly DependencyProperty
NoteProperty = DependencyProperty.Register("Note",
typeof(int), typeof(PatchRenderer),
new PropertyMetadata(
new PropertyChangedCallback(PatchRenderer.onNoteChanged)
));
private static void onNoteChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
// this is the bug: calling the setter in the callback
//((PatchRenderer)d).Note = (int)e.NewValue;
// the following was wrongly placed in the Note setter.
// it make sence to put it here.
// this method is intended to display stars icons
// to represent the Note
((PatchRenderer)d).UpdateNoteIcons();
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
11161 次 |
最近记录: |