wpf xaml资源字典添加自定义属性

时间:2015-12-16 16:04:42

标签: wpf xaml

我想在某些页面中使用以下xaml代码进行导航:

<Button Content="Go to page2">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <ei:ChangePropertyAction PropertyName="Source" TargetObject="{Binding NavigationService, RelativeSource={RelativeSource AncestorType={x:Type Page}, Mode=FindAncestor}}">
                <ei:ChangePropertyAction.Value>
                    <System:Uri>Page2.xaml</System:Uri>
                </ei:ChangePropertyAction.Value>
            </ei:ChangePropertyAction>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

所以我想知道是否有可能将交互部分外包到一个样式(在资源字典中)并添加一个自定义属性,如“NavigationUri”,您可以直接声明要导航到的页面。
另一个想法(可能是更好的方法)是创建自定义控件并从按钮类继承。 任何地方我都希望在没有代码的情况下采用更紧凑,更精益的方式。

请告诉我,这是更合适的解决方案以及如何实施。

3 个答案:

答案 0 :(得分:1)

虽然有各种简单的技术可以将我们的行为Xaml作为静态资源。但是,我们需要一个自定义行为,因为我们使用页面名称形式的参数导航到。这个变量需要编程。

所以,我想出了

一个。自定义行为(NavigationBehavior)和

湾按钮子类化(NavigationButton)

<强> NavigationBehavior

using System;
using System.Windows.Controls;
using System.Windows.Interactivity;

namespace WpfApplication1.Navigation
{
    public class NavigationBehavior:Behavior<NavigationButton>   
    {
        protected override void OnAttached()
        {
            AssociatedObject.Click += AssociatedObject_Click;
            base.OnAttached();
        }

        void AssociatedObject_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            ((Page)AssociatedObject.DataContext).NavigationService.Source = new Uri(AssociatedObject.DestinationUri, UriKind.Relative);
        }
    }
}

<强> NavigationButton

namespace WpfApplication1.Navigation
{
    public class NavigationButton : Button
    {
        NavigationBehavior behavior = new NavigationBehavior();

        public NavigationButton()
        {            
            behavior.Attach(this);
        }

        public string DestinationUri { get; set; }
    }
}

用法:

<nav:NavigationButton Content="Navigate to Page2" DestinationUri="/Navigation/Page2.xaml" />

重要提示

  1. 我们在行为中使用DataContext属性来访问包含页面。因此,在所有页面的构造函数中设置this.DataContext = this;
  2. 可以尝试使用公共基类/接口来避免这种情况。

答案 1 :(得分:0)

您无法提取交互式触发器,但有一种解决方法可以完成此操作

您可以在资源中创建一个包含交互逻辑的按钮,然后在需要的地方,您可以拥有一个内容控件,其内容设置为您的资源。

这样的事情 -

<Window.Resources>
    <Button x:Key="MyButton"
     Content="Go to page2">
<i:Interaction.Triggers>
    <i:EventTrigger EventName="Click">
        <ei:ChangePropertyAction PropertyName="Source" TargetObject="{Binding NavigationService, RelativeSource={RelativeSource AncestorType={x:Type Page}, Mode=FindAncestor}}">
            <ei:ChangePropertyAction.Value>
                <System:Uri>Page2.xaml</System:Uri>
            </ei:ChangePropertyAction.Value>
        </ei:ChangePropertyAction>
    </i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Window.Resources>


<Grid>
    <ContentControl Name="MyLocalButton" Content="{StaticResource MyButton}" />
</Grid>

答案 2 :(得分:0)

您应该将导航逻辑放在每个页面的视图模型中的命令中,并将按钮的Command属性绑定到这些命令,或者为视图模型分别提供NextPage属性并绑定到该属性。

在视图中创建单独的按钮。在资源字典中定义样式,使它们看起来都一样。

将Button定义为资源是个坏主意。除此之外,它只有一个实例,它只能有一个可视父级,所以当你将它添加到一个视图时,它将从最后一个消失。你遇到了像这样的丑陋问题。你正在对抗XAML,而当你使用XAML时,XAML已经很难了。