在WPF/Silverlight页面中设置自定义属性

Jon*_*eet 41 silverlight wpf xaml

这听起来应该很简单.我Page以正常方式在XAML中声明(即使用"添加新项目...")并且它具有自定义属性.我想在与页面关联的XAML中设置该属性.

尝试以我设置任何其他属性的方式执行此操作不起作用,原因我理解但不知道如何工作.就这样我们有一些具体的话题,这里有一些(无效的)XAML.我尽可能地减少了所有东西 - 最初有一些属性,比如设计师的尺寸,但我相信那些与我想要做的事情无关.

<Page x:Class="WpfSandbox.TestPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      MyProperty="MyPropertyValue">
</Page>
Run Code Online (Sandbox Code Playgroud)

和相应的代码隐藏:

using System.Windows.Controls;

namespace WpfSandbox {
  public partial class TestPage : Page {
    public TestPage() {
      InitializeComponent();
    }

    public string MyProperty { get; set; }
  }
}
Run Code Online (Sandbox Code Playgroud)

错误信息:

错误1 XML名称空间" http://schemas.microsoft.com/winfx/2006/xaml/presentation " 中不存在属性"MyProperty ".第4行位置7.

现在我知道为什么会失败:元素是类型的Page,并且Page没有调用的属性MyProperty.这只是在TestPage...中声明,由x:Class属性指定,但不是由元素本身指定.据我所知,XAML处理模型(即Visual Studio集成等)需要此配置.

我怀疑我可以使用依赖属性处理这个问题,但这有点像矫枉过正.我也可以使用现有属性(例如DataContext),然后在稍后的代码中将值复制到自定义属性中,但这将非常难看.

以上是一个WPF示例,但我怀疑相同的答案将适用于Silverlight.我对两者都很感兴趣 - 所以如果你发布一个你知道会在一个而不是另一个中工作的答案,如果你在答案中指出,我将不胜感激:)

当有人发布一个绝对琐碎的解决方案时,我正准备踢自己...

abh*_*hek 32

如果为页面创建Base类,则可以使用不带Dependency属性的普通属性.

 public class BaseWindow : Window
 {
   public string MyProperty { get; set; }
 }

<local:BaseWindow x:Class="BaseWindowSample.Window1" x:Name="winImp"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:BaseWindowSample" 
    MyProperty="myproperty value"
    Title="Window1" Height="300" Width="300">

</local:BaseWindow>
Run Code Online (Sandbox Code Playgroud)

即使MyProperty不是Dependency或Attached,它仍然有效.

  • -1敢于回答jon双向飞碟问题? (23认同)
  • @Filip:它看起来和Håvard的方法不一样 - 而且我仍然不知道*完全*你的意思是"丢失"`InitializeComponent()`.从哪一节课?(这里涉及两个.)它仍然存在于派生类中,似乎有效. (3认同)

Fil*_*erg 6

Pavel指出,你需要把它变成一个可附加的属性,然后你可以写这样的东西

<Page x:Class="JonSkeetTest.SkeetPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:JonSkeetTest="clr-namespace:JonSkeetTest" mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"
       JonSkeetTest:SkeetPage.MyProperty="testar"
    Title="SkeetPage">
    <Grid>

    </Grid>
</Page>
Run Code Online (Sandbox Code Playgroud)

但是只有这个代码背后:

您将收到此错误:

在'SkeetPage'类型中找不到可附加属性'MyProperty'.

附加属性"SkeetPage.MyProperty"未在"页面"或其基类之一上定义.


编辑

不幸的是,你必须使用Dependency Properties,她是一个有效的例子

<Page x:Class="JonSkeetTest.SkeetPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:JonSkeetTest="clr-namespace:JonSkeetTest" mc:Ignorable="d" 
      JonSkeetTest:SkeetPage.MyProperty="Testing.."
      d:DesignHeight="300" d:DesignWidth="300"
    Title="SkeetPage">

    <Grid>
        <Button Click="ButtonTest_Pressed"></Button>
    </Grid>
</Page>
Run Code Online (Sandbox Code Playgroud)

守则背后

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

namespace JonSkeetTest
{
    public partial class SkeetPage
    {
        public SkeetPage()
        {
            InitializeComponent();
        }

        public static readonly DependencyProperty MyPropertyProperty = DependencyProperty.Register(
          "MyProperty",
          typeof(string),
          typeof(Page),
          new FrameworkPropertyMetadata(null,
              FrameworkPropertyMetadataOptions.AffectsRender
          )
        );

        public static void SetMyProperty(UIElement element, string value)
        {
            element.SetValue(MyPropertyProperty, value);
        }
        public static string GetMyProperty(UIElement element)
        {
            return element.GetValue(MyPropertyProperty).ToString();
        }

        public string MyProperty
        {
            get { return GetValue(MyPropertyProperty).ToString(); }
            set { SetValue(MyPropertyProperty, value); }
        }

        private void ButtonTest_Pressed(object sender, RoutedEventArgs e)
        {
            MessageBox.Show(MyProperty);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果按下按钮,您将在MessageBox中看到"Testing ...".