使用MVVM Light

时间:2016-12-11 19:05:06

标签: c# .net wpf mvvm mvvm-light

如何使用MVVM Light创建一般用户控件?

应用程序中的所有主要视图似乎都可以正常工作。但是,一般控件似乎不接受绑定。这是我的FileDiplay控件。 一个图标和一个TextBlock,旁边显示一个文件名。

利用

在其中一个主视图中,我尝试在ItemsTemplate的{​​{1}}内绑定FileName。指定文字,如ItemsControl可以正常工作,但绑定不会。

FileName="xxx"

我一直在玩<local:FileLink FileName="{Binding FileName}" /> DependencyProperty。而且似乎没有办法绕过DependencyProperty,因为它不能被束缚。使用简单的INotifyPropertyChanged而不是此用户控件时,接受绑定。

我没有包含定位器或利用控件以避免过多的代码。事实上,我认为这是一个非常简单的问题,但我还没有找到解决方案。我确实认为将DataContext设置为ViewModel是正确的,因为没有列表绑定或真正的UserControl分离是可能的。我也调试了setter并尝试了不同的方法。

FileLink.xaml

TextBlock

FileLink.xaml.cs

<local:UserControlBase
    x:Class="....FileLink"
    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"
    xmlns:local="clr-namespace:..."
    mc:Ignorable="d" DataContext="{Binding FileLink, Source={StaticResource Locator}}">
    <Grid>
        <StackPanel Orientation="Horizontal">
            <Image Source="{Binding Icon}" Margin="0,0,5,0" />
            <TextBlock Text="{Binding FileName}" />
        </StackPanel>
    </Grid>
</local:UserControlBase>

FileLinkViewModel.cs

using System.Windows;
using System.Windows.Media;

namespace ...
{
    public partial class FileLink : UserControlBase
    {
        private FileLinkViewModel ViewModel => DataContext as FileLinkViewModel;
        public static DependencyProperty FileNameProperty = DependencyProperty.Register(nameof(FileName), typeof(string), typeof(FileLink));

        public ImageSource Icon
        {
            get
            {
                return App.GetResource("IconFileTypeCsv.png"); // TODO:...
            }
        }
        public string FileName
        {
            get
            {
                return ViewModel.FileName;
            }
            set
            {
                ViewModel.FileName = value;
            }
        }

        public FileLink()
        {
            InitializeComponent();
        }
    }
}

1 个答案:

答案 0 :(得分:2)

不要显式设置UserControl的DataContext,因为它有效地阻止了控件从其父控件继承DataContext,这就像你在Binding中所期望的那样

<local:FileLink FileName="{Binding FileName}" />

此外,不要像使用FileName属性那样包装视图模型属性。如果视图模型具有FileName属性,则上述绑定开箱即用,而不包含视图模型。

如果你真的需要UserControl中的FileName属性,它应该是一个常规的依赖属性

public partial class FileLink : UserControlBase
{
    public FileLink()
    {
        InitializeComponent();
    }

    public static readonly DependencyProperty FileNameProperty =
        DependencyProperty.Register(nameof(FileName), typeof(string), typeof(FileLink));

    public string FileName
    {
        get { return (string)GetValue(FileNameProperty); }
        set { SetValue(FileNameProperty, value); }
    }
}

并且您应该通过将UserControl指定为RelativeSource来绑定它:

<local:UserControlBase ...> <!-- no DataContext assignment -->
    <StackPanel Orientation="Horizontal">
        <Image Source="IconFileTypeCsv.png" Margin="0,0,5,0" />  
        <TextBlock Text="{Binding FileName,
                          RelativeSource={RelativeSource AncestorType=UserControl}}" />
    </StackPanel>
</local:UserControlBase>