使用MVVM Light创建通用的用户控件 [英] Creating generalized user controls with MVVM Light

查看:215
本文介绍了使用MVVM Light创建通用的用户控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用MVVM Light创建常规用户控件?

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

All the main views in the application seem to work fine. However, general controls doesn't seem to accept bindings. This is my FileDiplay control. An icon and a TextBlock displaying a filename next to it.

利用率

在其中一个主要视图中,我尝试在ItemsControlItemsTemplate内绑定FileName.指定文字,例如FileName="xxx"可以很好地工作,但是绑定则不能.

In one of the main views, I try to bind a FileName inside an ItemsTemplate of an ItemsControl. Specifying a literal, like FileName="xxx" works fine, but binding doesn't.

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

我经常玩DependencyPropertyINotifyPropertyChanged.似乎没有办法解决DependencyProperty,因为它不能以其他方式绑定.当使用简单的TextBlock而不是此用户控件时,将接受绑定.

I've been playing around with DependencyProperty and INotifyPropertyChanged a lot. And seemingly there's no way around a DependencyProperty, since it can't be bound otherwise. When using a simple TextBlock instead of this user control, binding is accepted.

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

I didn't include the locator or the utilizing control in order to avoid too much code. In fact, I think this is a very simple problem that I haven't found the solution for, yet. I do think that having the DataContext set to the ViewModel is correct, since no list binding or real UserControl separation is possible. I've also debugged into the setters and tried the different approaches.

FileLink.xaml

<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>

FileLink.xaml.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();
        }
    }
}

FileLinkViewModel.cs

using GalaSoft.MvvmLight;

namespace ...
{
    public class FileLinkViewModel : ViewModelBase
    {
        private string _FileName;
        public string FileName
        {
            get
            {
                return _FileName;
            }
            set
            {
                Set(() => FileName, ref _FileName, value);
            }
        }
    }
}

推荐答案

不要显式设置UserControl的DataContext,因为它有效地防止了该控件从其父控件继承DataContext,这是您在绑定中所期望的喜欢

Do not explicitly set the DataContext of your UserControl, because it effectively prevents that the control inherits the DataContext from its parent control, which is what you expect in a Binding like

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

此外,不要像使用FileName属性那样包装视图模型属性.如果视图模型具有FileName属性,则上述绑定可以直接使用,而无需对视图模型进行任何包装.

Also, do not wrap the view model properties like you did with the FileName property. If the view model has a FileName property, the above binding works out of the box, without any wrapping of the view model.

如果您确实需要UserControl中的FileName属性,它应该是常规的依赖项属性

If you really need a FileName property in the UserControl, it should be a regular dependency property

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来绑定到它:

and you should bind to it by specifying the UserControl as 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>

这篇关于使用MVVM Light创建通用的用户控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆