2

我有一个基本的 WinRT XAML UserControl,它具有如下实现的单个依赖项属性。用户控件显然只有在另一个 Page 或 UserControl 中使用时才在设计时构建。当我在设计器中使用用户控件本身工作时,不会呈现文本“Hello world”。在这种情况下,如何让设计器也用数据初始化用户控件?

XAML:

<UserControl
    x:Class="GTWin8.Ui.SimpleBinding"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:GTWin8.Ui"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400"
    x:Name="ThisControl">

    <Grid Background="Black">
        <TextBlock Text="{Binding Path=Message, ElementName=ThisControl}" 
                   HorizontalAlignment="Left" Margin="10,10,0,0" 
                   TextWrapping="Wrap" VerticalAlignment="Top" Height="280" Width="380"/>
    </Grid>
</UserControl>

代码隐藏:

public sealed partial class SimpleBinding : UserControl
{
    public static DependencyProperty MessageProperty = DependencyProperty.Register(
           "Message", typeof(String), typeof(SimpleBinding), new PropertyMetadata(null));

    public String Message
    {
        get { return (String)GetValue(MessageProperty); }
        set { SetValue(MessageProperty, value); }
    }

    public SimpleBinding()
    {
        this.InitializeComponent();
        Message = "Hello world";
    }
}
4

2 回答 2

5

好吧,一个更简单的方法是声明式调用。

<UserControl>

    <d:Page.DataContext>
        <sample:FakeViewModel />
    </d:Page.DataContext>

    <Grid>
        <!-- your bind/content -->
    </Grid>

</UserControl>

我在所有项目中都使用它,因为它提供设计时数据而不会影响我的运行时体验。更多:http ://blog.jerrynixon.com/2012/06/windows-8-15-more-reasons-why-i-choose.html

于 2012-08-09T17:40:13.400 回答
3

IIRC,以您编写的直接形式,这是不可能实现的,因为在设计时您不使用控件的实例。请注意 XAML 的第一行:根元素指定了 UserControl,即基类。这是您使用的实例!这就是为什么在设计带有抽象基类的组件时总是存在问题的原因。您在设计器中使用的所有内容都是一个 UserControl 实例,其中填充了 XAML 指定的内容。

XAML 分析器实例化由标记名称描述的任何对象。在您设计控件时,会阻止解析器实例化它,因为该控件实际上还不存在。这正是为什么 XAML 的第一个词是 UserControl 并且您的类名作为 x:Class 属性给出的原因。当您保存 XAML 时,它将被预处理为指定部分类的 MyControl.g.cs 文件,它将与您自己的 MyControl.cs 一起编译,然后 Visual Studio(或您的应用程序)才会能够调用它包含的代码。

如果您努力尝试,您可能会强制 XAML 解析器加载您的控件,但这是为了什么?您将获得 PREVIOUS 构建的快照,而不是当前编辑的快照。只有 XAML 模板保持最新,因为它们是动态删除和加载的。

这就是“为什么我的构造函数没有运行”的部分。

如果您需要在 ctor 中设置消息,为什么不将其设置为默认属性值?

public sealed partial class SimpleBinding : UserControl
{
    public static DependencyProperty MessageProperty = DependencyProperty.Register(
           "Message", typeof(String), typeof(SimpleBinding), new PropertyMetadata("Hello world"));
...
    public SimpleBinding()
    {
        this.InitializeComponent();
    }
}

当然,与您可以在构造函数中分支/计算/等相比,它受到严格限制和硬编码。如果您需要更多自由,请尝试使用 Design Time Data,也许这会有所帮助。

如果您确实需要在自己的单独设计时在组件内运行自定义代码,请考虑将代码移动到虚拟基类中,并将 <MyBaseClass> 而不是 <UserControl> 放在 XAML 的根目录中。XAML 解析器将被迫对其进行实例化,然后使用 xaml 的内容对其进行皮肤处理。请注意,您将调用该基类的先前成功构建。另外,请记住使用 IsInDesignMode 或类似方法(参见即https://stackoverflow.com/a/426072/717732)来过滤行为。

于 2012-08-08T15:09:09.390 回答