WPF .NET4.5
问题:当设置ImageCanvas上的ListSource依赖项属性时,只有最后一个行为“MyList”实际上会更新。就好像最后一个行为会覆盖所有以前的绑定。
如何在ImageCanvas上更新ListSource时更新所有行为?
我有一个带有ListSource依赖属性的自定义控件:
public class ImageCanvas : ContentControl
{
public FrameElement ListSource
{
get { return (FrameElement)GetValue(ListSourceProperty); }
set { SetValue(ListSourceProperty, value); }
}
// Using a DependencyProperty as the backing store for ListSource. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ListSourceProperty =
DependencyProperty.Register("ListSource", typeof(FrameElement), typeof(ImageCanvas),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
(s,e) =>
{
// The ListBehavior will be called before this dependency property of ImageCanvas.
ImageCanvas ic = s as ImageCanvas;
ic.Content = ((FrameElement)e.NewValue).DataContext;
}
));
}
}
XAML是:
<ctrl:ImageCanvas x:Name="ImageCanvas"
Grid.Column="1" Grid.Row="1" Background="Aquamarine"
Panel.ZIndex="{Binding ImageLayer.ZIndex}"
Visibility="{Binding ImageLayer.Visibility}"
>
<i:Interaction.Behaviors>
<b:ImageCanvasBehavior x:Name="MyZoom" />
<b:MovieBehavior x:Name="MyMovie" />
<b:MusicBehavior x:Name="MyMusic" />
<b:ListBehavior x:Name="MyList" />
</i:Interaction.Behaviors>
</ctrl:ImageCanvas>
当XAML加载ImageCanvas时,每个行为都绑定到ImageCanvas的ListSource定制属性。
在行为中:
private void IC_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
var ic = AssociatedObject as ImageCanvas;
var bindingListSource = new Binding();
bindingListSource.Source = this;
bindingListSource.Path = new PropertyPath(ListSourceProperty);
BindingOperations.SetBinding(ic, ImageCanvas.ListSourceProperty, bindingListSource);
}
public FrameElement ListSource
{
get { return (FrameElement)GetValue(ListSourceProperty); }
set { SetValue(ListSourceProperty, value); }
}
// Using a DependencyProperty as the backing store for ListSource. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ListSourceProperty =
DependencyProperty.Register("ListSource", typeof(FrameElement), typeof(ListBehavior), new PropertyMetadata(null,
(s,e) =>
{
var behavior = s as ListBehavior;
var ic = behavior.AssociatedObject as ImageCanvas;
if ((FrameElement)e.NewValue == (FrameElement)e.OldValue)
return;
CurrentFrame = ((FrameElement)e.NewValue).Frame;
}
));
问题:当设置ImageCanvas上的ListSource依赖项属性时,只有最后一个行为“MyList”实际上会更新。就好像最后一个行为会覆盖所有以前的绑定。
如何在ImageCanvas上更新ListSource时更新所有行为?
编辑#1:为了更好地解释,我已将“FrameElement”定义为:
public class FrameElement : UIElement
{
public object DataContext { get; set; }
public int Frame { get; set; }
public ListTypeEnum ListType { get; set; }
public string Title { get; set; }
}
ContentControl一次只用于显示一个项目,资源中的DataTemplates用于隐式更改基于DataContext的显示(这很有效)。 DataContext可能有也可能没有集合,具体取决于DataContext对当前显示的内容(因此为“Frame”编号)。问题是每个行为都需要确定当前的datacontext是否适用于自身 - 因此,当在ContentControl上设置时,每个行为(如XAML中所列)需要接收当前的FrameElement,即“ImageCanvas”。
我希望能更好地解释我的情景。
TIA。
编辑#2: 如果从行为中删除BindingOperations,并且XAML更改为直接绑定(参见下文),则所有行为都会正确更新! 现在的问题是,如何在行为中正确复制XAML代码以实现相同的结果???
使用XAML代码:
<ctrl:ImageCanvas x:Name="ImageCanvas"
Grid.Column="1" Grid.Row="1" Background="Aquamarine"
Panel.ZIndex="{Binding ImageLayer.ZIndex}"
Visibility="{Binding ImageLayer.Visibility}"
>
<i:Interaction.Behaviors>
<b:ImageCanvasBehavior x:Name="MyZoom"
ListSource="{Binding ElementName=ImageCanvas, Path=ListSource}" />
<b:MovieBehavior x:Name="MyMovie"
ListSource="{Binding ElementName=ImageCanvas, Path=ListSource}" />
<b:MusicBehavior x:Name="MyMusic"
ListSource="{Binding ElementName=ImageCanvas, Path=ListSource}" />
<b:ListBehavior x:Name="MyList"
ListSource="{Binding ElementName=ImageCanvas, Path=ListSource}" />
</i:Interaction.Behaviors>
</ctrl:ImageCanvas>