C# 通过绑定到UserConrol DependencyProperty传递参数
我有一个自定义用户控件,它只有一个属性-SubHeaderC# 通过绑定到UserConrol DependencyProperty传递参数,c#,wpf,xaml,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.
<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>
xaml中有两种用法。首先是常量文本:
...
<my:TopSection SubHeaderText="Constant text"/>
...
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);
}
}
}
问题是第二个不起作用。如果我传递常量文本-显示它,如果我使用绑定到其他属性-则不显示任何内容。
有人知道代码出了什么问题吗?谢谢。
MyModel
是您的DataContext
中的一个属性吗?尝试检查您的DataContext
是什么对象。如果数据上下文是类MyModel
的对象,则绑定中不需要MyModel.
部分。
这种绑定总是与数据上下文中的对象绑定
希望这些提示能有所帮助。像这样声明您的用户控件:
<my:TopSection
x:Name="myControl">
然后将您的绑定更改为:
<my:TopSection SubHeaderText="{Binding MyModel.SubHeaderText, ElementName=myControl}"/>
您没有在
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); }
}
}
更新
因为您不希望视图知道模型
。创建一个ViewModel
public class SampleViewModel : NotificationObject
{
public class MyModel { get; set; }
public class SampleViewModel()
{
MyModel = new MyModel() { SubHeaderText = "Sample" };
RaisePropertyChange("MyModel");
}
}
问题是您在UserControl
元素上设置了DataContext
。它将导致以下绑定
<my:TopSection SubHeaderText="{Binding MyModel.SubHeaderText}"/>
许多人将DataContext
设置在UserControl
上,但这确实不好。当您稍后使用UserControl时,您不知道DataContext
实际上是在内部设置的,并且不会尊重外部的DataContext
——真是令人困惑。此规则也适用于其他属性。如何设置TopSection
的DataContext
?我为TopSection添加了完整的xaml。Datacontext是这样设置的:Datacontext=“{Binding RelativeSource={RelativeSource Self}}}”MyHeader是如何创建的?您是指MyModel.SubHeaderText吗?如果是的话,这是一个get属性。请参阅上面的代码。请参阅更新。TopSection对MyModel一无所知。它在xaml中应该只有1个属性集。如果你不想让它知道你的模型。你的ViewModel在哪里?我的目标是让用户控件显示给定的任何文本(因此我使用了1个属性-我认为我不需要Model或ViewModel)。@Julia是的,你现在不需要它。等到您开始维护和扩展该类。你把他们耦合得太多了,你是对的。但我的问题不同了,现在已经解决了。虽然我真的不知道如何将要显示的文本传递给UserControl中使用的ViewModel。此更改会在错误列表中引发错误:对象引用未设置为对象。虽然我能够运行它-它仍然显示常量文本,无法显示绑定。更新:抱歉。我想那是对bug的。它现在可以正常工作了。太好了,谢谢@Julia在运行时检查输出窗口,应该有一行告诉您哪个绑定失败。@Julia太好了!许多人将DataContext
设置在UserControl
上,但这确实是件坏事,因为当您稍后使用UserControl
时,您不知道DataContext
实际上是内部设置的,不尊重外部DataContext
。真让人困惑。叮!我们公司已经多次遇到这个问题。小心直接在UserControl/Window/Page上设置DataContext。谢谢您的想法。MyModel的用法是正确的。这是我页面上的一个属性。并且DataContext被设置为self。
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); }
}
}
public class SampleViewModel : NotificationObject
{
public class MyModel { get; set; }
public class SampleViewModel()
{
MyModel = new MyModel() { SubHeaderText = "Sample" };
RaisePropertyChange("MyModel");
}
}
<my:TopSection SubHeaderText="{Binding MyModel.SubHeaderText}"/>
<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>