通过Binding将参数传递给UserConrol DependencyProperty

时间:2014-04-17 14:18:42

标签: c# wpf xaml

我有自定义用户控件,只有属性 - SubHeader。

<UserControl x:Class="ExpensesManager.TopSection"
  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" 
  DataContext="{Binding RelativeSource={RelativeSource Self}}"
  mc:Ignorable="d">
<StackPanel>
    <Label Name="Header" Content="Constant header text" Style="{StaticResource Header}"/>
    <Label Name="SubHeader" Content="{Binding SubHeaderText}" Style="{StaticResource SubHeader}"/>
</StackPanel>

public partial class TopSection : UserControl
{
    public TopSection()
    {
        this.InitializeComponent();
    }

    public static readonly DependencyProperty SubHeaderTextProperty =
        DependencyProperty.Register("SubHeaderText", typeof(string), typeof(TopSection));

    public string SubHeaderText
    {
        get { return (string)GetValue(SubHeaderTextProperty); }
        set { SetValue(SubHeaderTextProperty, value); }
    } 
}

xaml中有两种用法。首先是常量文本:

...
<my:TopSection SubHeaderText="Constant text"/>
...

另一个使用绑定:

<Page x:Class="MyNamespace.MyPage"
      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:my="clr-namespace:My"
      mc:Ignorable="d" 
      DataContext="{Binding RelativeSource={RelativeSource Self}}">
      ...
        <my:TopSection SubHeaderText="{Binding MyModel.SubHeaderText}"/>
      ...
</Page>

我的页面代码背后:

public partial class MyPage : Page
{
    private MyModel myModel;

    public MyModel MyModel
    {
        get
        {
            return this.myModel?? (this.myModel = new MyModel());
        }
    }

    public MyPage(MyEntity entity)
    {
        this.InitializeComponent();
        this.MyModel.MyEntity = entity;
    }
}

MyModel代码:

public class MyModel : NotificationObject
{
    private MyEntity myEntity;

    private string subHeaderText;

    public MyEntity MyEntity
    {
        get
        {
            return this.myEntity;
        }

        set
        {
            if (this.myEntity!= value)
            {
                this.myEntity= value;
                this.RaisePropertyChanged(() => this.MyEntity);
                this.RaisePropertyChanged(() => this.SubHeaderText);
            }
        }
    }

    public string SubHeaderText
    {
        get
        {
            return string.Format("Name is {0}.", this.myEntity.Name);
        }
    }
}

问题是第二个不起作用。如果我传递常量文本 - 它会显示,如果我使用绑定到其他属性 - 则不显示任何内容。 有人知道代码有什么问题吗?感谢。

4 个答案:

答案 0 :(得分:2)

问题是您在DataContext元素上设置了UserControl。它将导致以下绑定

<my:TopSection SubHeaderText="{Binding MyModel.SubHeaderText}"/>

相对于DataContextUserControl本身 - 因此无法找到该值。

要解决此问题,建议您不要在DataContext上设置UserControl,而在StackPanel内设置{/ 1}}:

<UserControl x:Class="ExpensesManager.TopSection"
  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" 
  mc:Ignorable="d">
<StackPanel DataContext="{Binding RelativeSource={RelativeSource AncesterType=UserControl}}">
    <Label Name="Header" Content="Constant header text" Style="{StaticResource Header}"/>
    <Label Name="SubHeader" Content="{Binding SubHeaderText}" Style="{StaticResource SubHeader}"/>
</StackPanel>

很多人在DataContext上设置了UserControl,但这确实是 BAD 。当您稍后使用UserControl时,您不知道DataContext实际上是在内部设置的,并且不会尊重外部DataContext - 实在令人困惑。此规则也适用于其他属性。

答案 1 :(得分:0)

MyModelDataContext中的媒体资源?尝试检查DataContext对象是什么。如果您的数据上下文是您的班级MyModel的对象,那么您在绑定中不需要MyModel.部分。 这种绑定始终是数据上下文中的对象。

希望这些提示有所帮助。

答案 2 :(得分:0)

像这样声明你的UserControl:

<my:TopSection
x:Name="myControl">

然后将绑定更改为:

<my:TopSection SubHeaderText="{Binding MyModel.SubHeaderText, ElementName=myControl}"/>

答案 3 :(得分:0)

您没有在UserControl

中设置模型
public partial class TopSection : UserControl
{ 

 public class SampleViewModel { get; set; }

 public TopSection()
 {
    this.InitializeComponent();
    this.DataContext = new SampleViewModel();
 }

 public static readonly DependencyProperty SubHeaderTextProperty =
    DependencyProperty.Register("SubHeaderText", typeof(string), typeof(TopSection));

 public string SubHeaderText
 {
    get { return (string)GetValue(SubHeaderTextProperty); }
    set { SetValue(SubHeaderTextProperty, value); }
 } 
}

<强>更新

因为您不希望Model知道View。创建ViewModel

public class SampleViewModel : NotificationObject
{  

  public class MyModel { get; set; }
  public class SampleViewModel()
  {
   MyModel = new MyModel() { SubHeaderText = "Sample" }; 
   RaisePropertyChange("MyModel");
  }  
}