如何将代码中的多个行为更新为自定义控件

时间:2017-07-31 06:09:30

标签: c# wpf xaml

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>

0 个答案:

没有答案