C# 带有ContentControl字段的自定义UserControl
我有一个C# 带有ContentControl字段的自定义UserControl,c#,wpf,xaml,windows-phone-7,C#,Wpf,Xaml,Windows Phone 7,我有一个UserControl,它充当ContentControl的包装器,它只是ContentControl的标题 <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid Background="Gre
UserControl
,它充当ContentControl
的包装器,它只是ContentControl
的标题
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Background="Green" Grid.Row="0">
<TextBlock Text="{Binding Header}" Style="{StaticResource HeaderStyle}" Margin="12, 10, 0, 10" />
</Grid>
<ContentControl HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Content="{Binding Body}" Grid.Row="1"/>
</Grid>
除了我在评论中所说的之外,您似乎在UserControl声明中绑定到了DataContext,这是一件坏事,也是所有这一切的问题所在 您似乎希望绑定到UserControl的属性,但直接绑定到DataContext的属性,DataContext是您的ViewModel,因此在XAML中的实例上设置Body属性没有任何作用,因为内部绑定避开了该属性 据我所知,UserControls应该执行如下绑定:
<UserControl Name="control" ...>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Background="Green" Grid.Row="0">
<TextBlock Text="{Binding Header, ElementName=control}" Style="{StaticResource HeaderStyle}" Margin="12, 10, 0, 10" />
</Grid>
<ContentControl HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Content="{Binding Body, ElementName=control}" Grid.Row="1"/>
</Grid>
将代码隐藏起来可能也很有用……这些属性更改回调的目的是什么?在我看来,除了将属性设置为它们已有的值之外,它们没有任何用途,因为这是一个属性更改回调,而不是一个属性更改回调。此外,在ViewModel中,您应该检查是否相等,并且只有在不相等时才更改raise属性。感谢您的响应。你的帖子中有很多信息,但是你是说不应该设置用户控件的DataContext,而ListHeader的CodeBehind应该具有属性吗?@willmel:在许多情况下,你希望UserControl能够绑定到继承的DataContext,如果你在UserControl中设置它,它将不会被插入。我不知道您的用例,所以这可能很好,但在许多情况下,可能会导致混淆,因为以DataContext为目标的实例上的绑定将以从外部看不见的内部集合为目标。我认为,视图是否应该为视图模型的创建负责,或者以其他方式负责,也存在一些争议,因此这一切都不是一成不变的。我不知道你关于房产的问题是什么意思…对不起,我不太明白。。你能链接到你描述的想法的一个例子吗?这就是我到目前为止一直在做的UserControls,但是如果它是一个糟糕的设计,我想改变它。删除DataContext实际上是修复方法,谢谢。我有一个内部类,它本身实际上有一些问题(传递了一个无效的值),这导致它无法呈现。它没有抛出异常,因为我想它是绑定堆栈的多个级别。谢谢@willmel:在数据绑定中,始终注意数据上下文是非常重要的,这就是为什么我建议不要设置它,除非它确实是必要的,很高兴您能够解决您的问题。
public partial class ListHeader : UserControl
{
private readonly ListHeaderData _data = new ListHeaderData();
public ListHeader()
{
InitializeComponent();
DataContext = _data;
}
public string Header
{
get { return (string)GetValue(HeaderProperty); }
set { SetValue(HeaderProperty, value); }
}
// Using a DependencyProperty as the backing store for Header. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HeaderProperty =
DependencyProperty.Register("Header", typeof(string), typeof(ListHeader), new PropertyMetadata("",HeaderPropertyChanged) );
private static void HeaderPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var lh = d as ListHeader;
if (lh != null)
lh._data.Header = e.NewValue as string;
}
public object Body
{
get { return GetValue(BodyProperty); }
set { SetValue(BodyProperty, value); }
}
// Using a DependencyProperty as the backing store for Body. This enables animation, styling, binding, etc...
public static readonly DependencyProperty BodyProperty =
DependencyProperty.Register("Body", typeof(object), typeof(ListHeader), new PropertyMetadata(null, BodyPropertyChanged));
private static void BodyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var lh = d as ListHeader;
if (lh != null)
lh._data.Body = e.NewValue;
}
}
public class ListHeaderData : ViewModelBase
{
public ListHeaderData()
{
if (IsInDesignMode)
{
Header = "Custom Header Goes Here";
Body = new Grid() { Background = new SolidColorBrush(Colors.Yellow) };
}
}
private string _header;
public string Header
{
get { return _header; }
set { _header = value; RaisePropertyChanged("Header"); }
}
private object _body;
public object Body
{
get { return _body; }
set { _body = value; RaisePropertyChanged("Body");}
}
}
<UserControl Name="control" ...>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Background="Green" Grid.Row="0">
<TextBlock Text="{Binding Header, ElementName=control}" Style="{StaticResource HeaderStyle}" Margin="12, 10, 0, 10" />
</Grid>
<ContentControl HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Content="{Binding Body, ElementName=control}" Grid.Row="1"/>
</Grid>
private int _MyProperty = 0;
public int MyProperty
{
get { return _MyProperty; }
set
{
if (_MyProperty != value)
{
_MyProperty = value;
OnPropertyChanged("MyProperty");
}
}
}