在另一个UserControl内部,Universal App XAML绑定无法在UserControl上运行

时间:2016-09-23 08:08:26

标签: c# xaml user-controls win-universal-app

我目前正在开发Windows通用应用程序。我对XAML一般都很陌生,但对它有一些经验。

我遇到的问题是围绕UserControl绑定。我环顾四周,找不到具体问题的答案。

我有一个链接到ViewModel的XAML页面,这一切都正常。然后在那个页面上,我使用的是UserControl,它基本上只是一个包含一些内容的标题的面板。在该面板的内容中,我有另一个UserControl,它基本上只包含一个Label和TextBox。

当我将ViewModel中的内容绑定到ContentPanel UserControl时,一切正常,它会拾取我的ViewModel上下文并正确绑定。

但是,当我尝试绑定到包含ContentPanel的LabelledTextbox UserControl时,绑定失败,因为它只是在ContentPanel上查找ViewModel上的属性。

请参阅下面的代码

Page.xaml

<!--Page.xaml-->                    
<cc:ContentPanel PanelHeading="LEFT FOOT: Measurements" PanelHeadingBackground="{StaticResource OPCare.PanelHeader}">
                    <StackPanel>
                        <cc:LabelledTextbox LabelText="Malleoli Width" Text="test" />
                        <cc:LabelledTextbox LabelText="Met Head Width" />
                    </StackPanel>
                </cc:ContentPanel>

ContentPanel.xaml

<!--ContentPanel UserControl-->
<UserControl
    x:Class="OrthoticTabletApp.Controls.ContentPanel"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:OrthoticTabletApp.Controls"
    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="Parent">

    <Grid DataContext="{Binding ElementName=Parent}">
        <Grid.RowDefinitions>
            <RowDefinition Height="50" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <Grid Padding="10" Grid.Column="0" Grid.Row="0" Height="50" Background="{Binding Path=PanelHeadingBackground}">
            <TextBlock Height="30" LineHeight="30" Text="{Binding Path=PanelHeading}" />
        </Grid>

        <Grid Padding="10" Grid.Column="0" Grid.Row="1" Background="White">
            <ContentPresenter Content="{Binding Path=PanelBody}" />
        </Grid>

    </Grid>
</UserControl>

ContentPanel.xaml.cs

[ContentProperty(Name = "PanelBody")]

public sealed partial class ContentPanel : UserControl
{

    public static readonly DependencyProperty PanelHeadingProperty = DependencyProperty.Register("PanelHeading", typeof(string), typeof(ContentPanel), new PropertyMetadata(""));

    public string PanelHeading
    {
        get
        {
            return (string)GetValue(PanelHeadingProperty);
        }
        set
        {
            SetValue(PanelHeadingProperty, value);
        }
    }

    public static readonly DependencyProperty PanelBodyProperty = DependencyProperty.Register("PanelBody", typeof(object), typeof(ContentPanel), new PropertyMetadata(null));

    public object PanelBody
    {
        get
        {
            return (object)GetValue(PanelBodyProperty);
        }
        set
        {
            SetValue(PanelBodyProperty, value);
        }
    }

    public Brush PanelHeadingBackground
    {
        get { return (Brush)GetValue(PanelHeadingBackgroundProperty); }
        set { SetValue(PanelHeadingBackgroundProperty, value); }
    }

    public static readonly DependencyProperty PanelHeadingBackgroundProperty =
        DependencyProperty.Register("PanelHeadingBackground", typeof(Brush), typeof(ContentPanel), new PropertyMetadata(null));

    public ContentPanel()
    {
        this.InitializeComponent();
    }
}

LabelledTextbox.xaml

<UserControl
    x:Class="OrthoticTabletApp.Controls.LabelledTextbox"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:OrthoticTabletApp.Controls"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="50"
    d:DesignWidth="400"
    x:Name="Parent">

    <Grid DataContext="{Binding ElementName=Parent}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="300" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <Grid Grid.Column="0" Padding="10">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="15" />
            </Grid.ColumnDefinitions>

            <TextBlock Grid.Column="0" Text="{Binding Path=LabelText}" />

        </Grid>

        <Grid Grid.Column="1" Padding="10">
            <TextBox Text="{Binding Path=Text}" />
        </Grid>
    </Grid>
</UserControl>

LabelledTextbox.xaml.cs

public sealed partial class LabelledTextbox : UserControl
    {
        public string LabelText
        {
            get { return (string)GetValue(LabelTextProperty); }
            set { SetValue(LabelTextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for LabelText.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty LabelTextProperty =
            DependencyProperty.Register("LabelText", typeof(string), typeof(LabelledTextbox), new PropertyMetadata(null));

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(LabelledTextbox), new PropertyMetadata(null));

        public LabelledTextbox()
        {
            this.InitializeComponent();
        }
    }

1 个答案:

答案 0 :(得分:0)

  

但是,当我尝试绑定到ContentPanel包含的LabelledTextbox UserControl时,绑定失败,因为它只是在ContentPanel上查找ViewModel上的属性。

如果我正确理解您已完成的操作,则ContentPanel的某些属性会绑定到页面视图模型中的数据模型,并且LabelledTextbox的属性会受到约束到其他viewmodel中的数据模型?

如果有,您可以为DataContext中的LabelledTextbox指定StackPanel的{​​{1}},例如:{/ p>

ContentPanel

在您网页的视图模型中,您可以为<cc:ContentPanel PanelHeading="{x:Bind Heading}" PanelHeadingBackground="Azure"> <StackPanel> <StackPanel.DataContext> <local:LabelledTextboxViewModel x:Name="VM" /> </StackPanel.DataContext> <cc:LabelledTextbox LabelText="{x:Bind VM.Lable1}" Text="test" /> <cc:LabelledTextbox LabelText="{x:Bind VM.Lable2}" /> </StackPanel> </local:ContentPanel> 创建数据模型并初始化数据,例如:

ContentPanel

在LabelledTextboxViewModel中,您可以编写如下代码:

public BlankPage3ViewModel()
{
    Heading = "LEFT FOOT: Measurements";
}

public string Heading { get; set; }

通常当我们按照MVVM模式开发项目时,数据模型不应该包含在viewmodel中,我这里只是为了清晰易行的交付,关键点是您可以为同一页面中的不同控件指定不同的public class LabelledTextboxViewModel { public LabelledTextboxViewModel() { Lable1 = "Malleoli Width"; Lable2 = "Met Head Width"; } public string Lable1 { get; set; } public string Lable2 { get; set; } }