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");
        }
    }
}