了解依赖对象

时间:2014-11-21 13:14:09

标签: wpf xaml mvvm user-controls

我完全失去了依赖对象和绑定。我常常在不了解原因和方法的情况下开展工作,这个问题就是要知道应该发生什么。

我有一个微小的用户控件,带有以下XAML

<Grid>
    <Image Source="{Binding Icon}"></Image>
    <TextBlock Text="{Binding Title}"></TextBlock>
</Grid>

我的代码背后有

    public static readonly DependencyProperty IconProperty =
     DependencyProperty.Register("Icon", typeof(Image), typeof(MenuItem));

    public Image Icon
    {
        get { return (Image)GetValue(IconProperty); }
        set { SetValue(IconProperty, value); }
    }

    public static readonly DependencyProperty TitleProperty =
     DependencyProperty.Register("Title", typeof(String), typeof(MenuItem));


    public string Title
    {
        get { return (string)GetValue(IconProperty); }
        set { SetValue(IconProperty, value); }
    }

除了对此控件和ResourceDictionary的引用之外,我的MainWindow是空的。在后面的MainWindow代码中,我在构造函数中设置了DataContext。

   <Window x:Class="AppUi.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:loc="clr-namespace:AppUi.Control"
    Title="">
     //set up to Resource Dictionary - all binding and styling works fine :)
    <loc:MenuItem Icon="{Binding MailIcon}" Title="{Binding MailTitle}"></loc:MenuItem>

在MainWindow的ModelView中,我有以下2个属性

    private Image_mailIcon;
    public Image MailIcon{
          //inotifyproperty implementation 
    }

    private string _mailTitle;
    public string MailTitle{
          //inotifyproperty implementation 
    }

我的问题是,在UserControl中,我该如何进行绑定?由于它是MainWindow中的用户控件,并且MainWindow已经有一个datacontext,我认为UserControl将从父级继承DataContext(从我读过的内容)。

那么,在我的UserControl XAML中,我应该绑定到MainWindow的Code Behind属性还是ViewModel属性?

换句话说,我的UserControl应该是

<Grid>
    <Image Source="{Binding MailIcon}"></Image>
    <TextBlock Text="{Binding MailTitle}"></TextBlock>
</Grid>

OR

<Grid>
    <Image Source="{Binding Icon}"></Image>
    <TextBlock Text="{Binding Title}"></TextBlock>
</Grid>

或者,因为我使用的是DataContext并且UserControl继承了,我甚至还需要Dependancy Properties吗?

2 个答案:

答案 0 :(得分:1)

您通常不想覆盖通过可视树传递的DataContext,因此您可以使用ElementName内的RelativeSourceUserControl绑定来更改绑定上下文。实现此目标的最简单方法是为UserControl提供一些名称并使用ElementName绑定

<UserControl ... x:Name="myUserControl">
    <!-- ... -->
    <Grid>
        <Image Source="{Binding Icon, ElementName=myUserControl}"/>
        <TextBlock Text="{Binding Title, ElementName=myUserControl}"/>
    </Grid>
    <!-- ... -->
</UserControl>

这种绑定方式DataContext是独立的。您也可以创建UserControl,并假设它始终只使用特定类型的DataContext,然后您只使用该视图模型类型中的Path,然后DataContext { {1}}必须始终属于其设计的视图模型(主要通过可视树继承)

UserControl

我还会将<UserControl ...> <!-- ... --> <Grid> <Image Source="{Binding MailIcon}"/> <TextBlock Text="{Binding MailTitle}"/> </Grid> <!-- ... --> </UserControl> 属性的类型从Icon更改为Image。您已在ImageSource内部拥有Image控制权,而您只想绑定其UserControl

答案 1 :(得分:1)

  在UserControl中

,我该如何进行绑定? ... UserControl将从父

继承DataContext

这是正确的,UserControl将从父DataContext继承Window。因此,您可以数据从UserControl直接绑定到父Window.DataContext。请注意,无论是后面的代码还是单独的视图模型类,您都将绑定到已设置为DataContext的任何对象。

但是,在这种情况下,您没有 将数据绑定到父{q} DataContext对象...您还有其他选择。您可以使用RelativeSource Binding 数据绑定到您自己的UserControl DependencyProperty

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

您也可以为UserControl命名并引用其属性,如下所示:

<TextBlock Text="{Binding Title, ElementName=YourUserControlName}" />

虽然这个例子似乎更简洁,但不要忽视第一个例子,因为RelativeSource是一个有用且有实力的朋友。

  

我应该绑定到MainWindow的Code Behind属性还是ViewModel属性?

这是您的选择......您想要或需要数据绑定到什么?您只需要知道直接数据绑定将使用自动设置DataContext值,因此如果您不想使用它,那么您只需为{{1}指定不同的数据源如上所示。

最后,关于使用Binding的需要......如果您正在开发需要提供数据绑定功能的DependencyProperty ,则只需要声明它们