【问题标题】:Binding a property that hides another in WinRT XAML (Windows8, Metro, Windows Store App)绑定在 WinRT XAML(Windows8、Metro、Windows 应用商店应用程序)中隐藏另一个属性的属性
【发布时间】:2013-03-25 17:26:37
【问题描述】:

首先我想说:请不要建议替代解决方案,除非您可以在不修改 BaseXXXXXX 模式的类型的情况下完成它

也就是说,就我而言,这种行为超出了令人困惑的范围,似乎使用 new 关键字来隐藏 C# 中的属性意味着 WinRT XAML(Windows8、Metro、Windows Store App)绑定不再正常工作。我不知道这是为什么。

这是一个例子:

C#:

namespace WinRtSandbox
{
    public class BaseClass 
    {
        public string Property1 { get; set; }
        public int[] Property2 { get; set; }
        public object Property3 { get; set; }
    }


    public class ModifiedClass : BaseClass
    {
        public new string Property1 { get; set; }
        public new long[] Property2 { get; set; }
        public new string Property3 { get; set; }
    }

    public sealed partial class MainPage : Page
    {

        public BaseClass Normal { get; set; }
        public ModifiedClass Modified { get; set; }

        public MainPage()
        {
            this.Normal = new BaseClass
            {
                Property1 = "WTF",
                Property2 = new[] { 2, 3, 4 },
                Property3 = "Work?"
            };

            this.Modified = new ModifiedClass
            {
                Property1 = "WTF",
                Property2 = new[] { 2L, 3L, 4L },
                Property3 = "Work?"
            };

            this.InitializeComponent();
        }
    }
}

WinRT XAML:

<Page
    x:Class="WinRtSandbox.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WinRtSandbox"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    mc:Ignorable="d">

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <Border Background="#22000000" Padding="40" Width="400" Height="500">
            <Grid>

                <Grid.Resources>
                    <Style TargetType="Rectangle">
                        <Setter Property="Height" Value="1"/>
                        <Setter Property="HorizontalAlignment" Value="Stretch"/>
                        <Setter Property="Margin" Value="0,15,0,15"/>
                        <Setter Property="Fill" Value="{StaticResource ApplicationForegroundThemeBrush}"/>
                    </Style>
                </Grid.Resources>

                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>

                <StackPanel Grid.Column="0">

                    <ItemsControl>
                        <TextBlock Text="this.Normal"/>
                        <Rectangle/>
                        <TextBlock Text="this.Normal.Property1"/>
                        <Rectangle/>
                        <TextBlock Text="this.Normal.Property2"/>
                        <Rectangle/>
                        <TextBlock Text="this.Normal.Property3"/>
                    </ItemsControl>

                    <Rectangle Fill="Red"/>

                    <ItemsControl>
                        <TextBlock Text="this.Modified"/>
                        <Rectangle/>
                        <TextBlock Text="this.Modified.Property1"/>
                        <Rectangle/>
                        <TextBlock Text="this.Modified.Property2"/>
                        <Rectangle/>
                        <TextBlock Text="this.Modified.Property3"/>
                    </ItemsControl>

                </StackPanel>

                <StackPanel Grid.Column="1">

                    <ItemsControl DataContext="{Binding Normal}">
                        <TextBlock Text="{Binding}"/>
                        <Rectangle/>
                        <TextBlock Text="{Binding Property1}"/>
                        <Rectangle/>
                        <TextBlock Text="{Binding Property2}"/>
                        <Rectangle/>
                        <TextBlock Text="{Binding Property3}"/>
                    </ItemsControl>

                    <Rectangle Fill="Red"/>

                    <ItemsControl DataContext="{Binding Modified}">
                        <TextBlock Text="{Binding}"/>
                        <Rectangle/>
                        <TextBlock Text="{Binding Property1}"/>
                        <Rectangle/>
                        <TextBlock Text="{Binding Property2}"/>
                        <Rectangle/>
                        <TextBlock Text="{Binding Property3}"/>
                    </ItemsControl>

                </StackPanel>
            </Grid>
        </Border>

    </Grid>
</Page>

完全不正确的结果如下所示:

基本上,这些空白行中的每一行都应该被填充你们中的任何一个 XAML 能手知道为什么这些绑定会失败吗?有什么办法可以解决我只能解决的问题吗?假设是一个令人发指的错误?任何帮助或见解将不胜感激,在此先感谢您...-ck

更新:我忘记的输出转储

Error: BindingExpression path error: 'Property2' property not found on 'WinRtSandbox.ModifiedClass'. BindingExpression: Path='Property2' DataItem='WinRtSandbox.ModifiedClass'; target element is 'Windows.UI.Xaml.Controls.TextBlock' (Name='null'); target property is 'Text' (type 'String')
Error: BindingExpression path error: 'Property3' property not found on 'WinRtSandbox.ModifiedClass'. BindingExpression: Path='Property3' DataItem='WinRtSandbox.ModifiedClass'; target element is 'Windows.UI.Xaml.Controls.TextBlock' (Name='null'); target property is 'Text' (type 'String')

更新:

向 Microsoft 提交的错误:https://connect.microsoft.com/VisualStudio/feedback/details/782993/binding-a-property-that-hides-another-in-winrt-xaml,我们将看看情况如何

【问题讨论】:

  • 输出中是否有任何内容表明绑定失败?我认为它只是变得混乱,因为该对象的 2 个属性具有相同的名称,但我找不到任何关于该主题的文献。
  • @KevinDiTraglia 抱歉,我忘了包含绑定转储,感谢您提醒我,该错误更没有意义,因为它听起来好像根本不存在该名称的属性...冲突消息我至少会明白
  • 嗯,出事了。我刚刚逐字加载了您的代码,它工作正常(用 WTF 填充每一行正在进行此操作)。这可能是 INotifyPropertyChanged 的​​问题(但如果您在构造函数中填写所有内容,我对此表示怀疑),或者表单的 DataContext 未设置为您认为的那样?不确定,但是将您所拥有的内容复制到一个空白项目中似乎对我有用。这是 .NET 4.0 吗? (另外我使用的是 WPF 窗口,而不是 windows phone 页面,这也可能有所不同?)
  • WinRT (Windows 8)...Windows 应用商店应用程序,而不是 WPF....但是如果这在 WPF 中有效,我认为这可能是框架中的某种错误(它在技术上是 .NET 4.5,但它是它自己的东西......)抱歉没有更清楚,我忘记并不是每个人都像我一样对 WinRT(Windows8)有深入了解并且不知道新的术语。我为下一个人编辑了一些问题:-D
  • 好的,我只能确认上述代码在 .NET 4.0 中的常规 WPF 应用程序中确实有效(通常两者非常相似)。抱歉,我无法提供更多帮助。

标签: c# xaml microsoft-metro windows-runtime windows-store-apps


【解决方案1】:

我同意这确实是一个错误。

我知道你说过你不想要替代品,但为了其他可能读到这个问题的人,我会忽略你。

您可以通过将每个属性设置为 DependencyProperty 来解决此问题

public class BaseClass : DependencyObject
{
    public static readonly DependencyProperty Property1Property = DependencyProperty.Register(
        "Property1",
        typeof(string),
        typeof(BaseClass),
        new PropertyMetadata(null));

    public string Property1
    {
        get { return (string)GetValue(Property1Property); }
        set { SetValue(Property1Property, value); }
    }

    public static readonly DependencyProperty Property2Property = DependencyProperty.Register(
        "Property2",
        typeof(int[]),
        typeof(BaseClass),
        new PropertyMetadata(null));

    public int[] Property2
    {
        get { return (int[])GetValue(Property2Property); }
        set { SetValue(Property2Property, value); }
    }

    public static readonly DependencyProperty Property3Property = DependencyProperty.Register(
        "Property3",
        typeof(object),
        typeof(BaseClass),
        new PropertyMetadata(null));

    public object Property3
    {
        get { return GetValue(Property3Property); }
        set { SetValue(Property3Property, value); }
    }
}


public class ModifiedClass : BaseClass
{
    public static readonly new DependencyProperty Property1Property = DependencyProperty.Register(
        "Property1",
        typeof(string),
        typeof(ModifiedClass),
        new PropertyMetadata(null));

    public new string Property1
    {
        get { return (string)GetValue(Property1Property); }
        set { SetValue(Property1Property, value); }
    }

    public static readonly new DependencyProperty Property2Property = DependencyProperty.Register(
        "Property2",
        typeof(long[]),
        typeof(ModifiedClass),
        new PropertyMetadata(null));

    public new long[] Property2
    {
        get { return (long[])GetValue(Property2Property); }
        set { SetValue(Property2Property, value); }
    }

    public static readonly new DependencyProperty Property3Property = DependencyProperty.Register(
        "Property3",
        typeof(string),
        typeof(ModifiedClass),
        new PropertyMetadata(null));

    public new string Property3
    {
        get { return (string)GetValue(Property3Property); }
        set { SetValue(Property3Property, value); }
    }
}

【讨论】:

  • 不修改基础的原因是因为它是不同项目的一部分,不能修改。如果您可以修改基类,为什么还要费心对其进行子类化并使用new 运算符?这样做是不合适的,如果您可以修改基础,只需首先使其成为正确的类型。通过子类化,特别是在 MVVM 模式中,为持久性或 UI 层在数据传输对象上“添加”或“更改”属性很常见。感谢您的努力和时间,但这对任何人都没有帮助,因为修改基类的能力已经缓解了这个问题。
  • @ckozl 是的,我知道您不想要替代品,并猜测正是出于这个原因。即使可以,我也可以设想一些您不只是更改基类类型的原因(例如重新调整您在项目其他地方广泛使用的大型类)。
【解决方案2】:

事实证明这是一个“不受支持的错误”,无论这意味着什么......这是直接引用:

您好,很抱歉我们回复晚了。到目前为止,我们不支持此错误。 请转至http://support.microsoft.com 或致电 1-800-MICROSOFT 帮助。谢谢。

...希望这将在 .NET 4.5.1 中得到修复

查看错误报告: https://connect.microsoft.com/VisualStudio/feedback/details/782993/binding-a-property-that-hides-another-in-winrt-xaml

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-14
    • 2012-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多