WPF用户控件:我可以绑定内部和外部datacontext的属性吗?

时间:2015-01-14 08:52:52

标签: wpf xaml mvvm data-binding calendar

我正在尝试在WPF / XAML中构建自己的日历控件,既可以作为练习,也可以用于业余爱好项目。该日历将是一个网格,其中每个单元格显然代表所选月份中的一天。每个单元格应该能够显示项目列表。日历的输入应该是一个月的标识和一个天的列表。那些“天”将是自定义类型,类似于

public class CalendarDay
{
    public int DayNumber {get; set;}
    public List<DayItem> Items {get; set;}
}

其中DayItem可以表示约会或待办事项。

我正在将其作为用户控件实现。此日历的XAML为ControlTemplate,其中包含{1}} 1x7的日期名称(绑定到集合7个字符串的数据)和UniformGrid 6x7的日期(数据绑定)到UniformGrid)的集合。

包含此日历的视图(用户控件)在概念上如下所示:

CalendarDay

当我正在应用MVVM时,<UserControl name="myView" ... xmlns:cal="clr-namespace:the calendar namespace"> <Grid> <cal:Calendar Days="{Binding DaysWithItems}" CurrentMonth="{Binding DisplayMonth}" /> </Grid> </UserControl> 将有一个DataContext设置为某个视图模型类,该类具有属性myViewDaysWithItems实例列表)和属性CalenderDay

理想情况下,此日历控件的使用者只需提供所述的两个输入。此外,DisplayMonth应该从DaysWithItems的角度(双关语是偶然的),是28,29,30或31个元素的列表,具体取决于月份。这意味着列表应该以某种方式填充到42个项目。我认为这应该是日历控件的责任,而不是myView的视图模型。

请注意,我也没有提供日期名称。这也应该是日历控件的责任。这不应该明确提供。

这是我的问题。如果在日历的控件模板中,我想绑定到日期名称的字符串集合和myView的42元素集合,那么datacontext应该是CalendarDay类本身(因为我的职责)先前解释过)。 另一方面,在Calendar中,我将日历绑定到myView的{​​{1}}(包含28..31个元素的(逻辑)集合),所以有日历的datacontext应该是myView的视图模型。

我可以使用某种内部datacontext(=控件模板的“内部”)以及某种外部datacontext(=日历控件使用者提供的datacontext)吗?

2 个答案:

答案 0 :(得分:2)

绑定到DataContext以外的其他内容的最简单方法是使用ElementName

您可以执行以下操作:

UserControl.xaml.cs的示例:

public partial class UserControl1 : UserControl
    {
        public UserControl1()
        {
            InitializeComponent();
        }



        public int MyProperty
        {
            get { return (int)GetValue(MyPropertyProperty); }
            set { SetValue(MyPropertyProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MyPropertyProperty =
            DependencyProperty.Register("MyProperty", typeof(int), typeof(UserControl1), new PropertyMetadata(0));


    }

UserControl.Xaml

<UserControl x:Class="GridSplitterTest.UserControl1"
             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" x:Name="MyControl"
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <Button Content="{Binding ElementName=MyControl, Path=MyProperty}"></Button>
    </Grid>
</UserControl>

通过使用ElementName并指向UserControl,您绕过了DataContext并能够绑定到UC内的属性。

答案 1 :(得分:1)

这是这类数据绑定的低端。如果要将数据绑定到设置为DataContext的对象的属性,则使用普通Binding Path

<TextBlock Text="{Binding PropertyOfDataContextObject}" />

但是,如果您还希望将数据绑定到属性(来自UserControl(或UserControl)中声明的Window内部),则应使用{{3 }}:

<TextBlock Text="{Binding PropertyOfUserControl, RelativeSource={RelativeSource 
    AncestorType={x:Type YourPrefix:YourUserControl}}}" />

您也可以为控件命名并使用RelativeSource Binding来引用它:

<TextBlock Text="{Binding PropertyOfNamedControl, ElementName=NameOfControl}" />