Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding a property that hides another in WinRT XAML (Windows8, Metro, Windows Store App)

right up front i want to say: please don't suggest alternative solutions, unless you can accomplish it without modifying the Types that are of the pattern BaseXXXXXX

that said, this behavior goes way beyond perplexing as far as I am concerned, it would seem that using the new keyword in order to hide a property in C# means that WinRT XAML (Windows8, Metro, Windows Store App) binding no longer functions correctly. I have no idea why this is.

Here is an example:

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>

The all-too-incorrect result looks something like: what is going on

basically, every one of those blank lines should be filled do any of you XAML hotshots have any idea why these bindings are failing and is there anything that can be done to work around what I can only assume is a heinous bug? Any help or insight would be greatly appreciated, thank you in advance... -ck

update: the output dump i forgot

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')

Update:

Bug filed with Microsoft: https://connect.microsoft.com/VisualStudio/feedback/details/782993/binding-a-property-that-hides-another-in-winrt-xaml so we'll see how that goes

like image 374
ckozl Avatar asked Apr 03 '13 20:04

ckozl


1 Answers

I agree it does a appear to be a bug.

I know you said you don't want alternatives, but for the sake of anyone else who might read this question, I'll ignore you.

You can fix this is by making the properties each into a 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); }
    }
}
like image 61
Murkaeus Avatar answered Oct 31 '22 17:10

Murkaeus