2016-12-11 67 views
0

如何使用MVVM Light創建一般用戶控件?使用MVVM Light創建一般用戶控件

在應用程序中的所有主視圖似乎工作正常。但是,一般控制似乎並不接受綁定。這是我的FileDiplay控件。 一個圖標和一個顯示文件名旁邊的TextBlock。


利用

在主視圖中的一個,我試圖綁定一個ItemsControlItemsTemplate內的文件名。指定文字,如FileName="xxx"可以正常工作,但綁定不會。

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

我一直在DependencyPropertyINotifyPropertyChanged很多玩耍。看起來沒有辦法解決DependencyProperty,因爲它不能被綁定。當使用簡單的TextBlock而不是此用戶控件時,綁定被接受。


我沒有包含定位器或利用控件,以避免代碼太多。事實上,我認爲這是一個非常簡單的問題,我還沒有找到解決方案。我認爲將DataContext設置爲ViewModel是正確的,因爲沒有列表綁定或真正的UserControl分離是可能的。我也調試了setters並嘗試了不同的方法。

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); 
      } 
     } 
    } 
} 
+0

「我確實認爲將DataContext設置爲ViewModel是正確的「。我不這麼認爲。顯式設置UserControl的DataContext實際上總是錯誤的。它可以防止UserControl繼承其父控件的DataContext,這是您通常在使用控件時所期望的內容,例如,乳清你寫'FileName =「{綁定文件名}」'。 – Clemens

+0

但是,這是否意味着屬性名稱必須匹配?我很可能會誤解這一點。當沒有指定DataContext時,如何正確設置屬性? – bytecode77

+0

在UserControl的XAML中,您將使用RelativeSource編寫綁定。看到這裏:http://stackoverflow.com/a/25699347/1136211 – Clemens

回答

2

不明確設置的DataContext你的用戶控件的,因爲它有效地防止了控制從其父控制,這是繼承的DataContext你在一個結合樣

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

也期待什麼,不裹視圖模型像您對FileName屬性所做的那樣。如果視圖模型具有FileName屬性,則上面的綁定可以直接使用,而不需要包裝視圖模型。

如果你真的需要在用戶控件一個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); } 
    } 
} 

,你應該通過指定用戶控件作爲的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> 
+0

所以我也不再需要ViewModel,而且最重要的是:它的工作原理! :) +1 ...附註:有什麼辦法可以簡化這個綁定表達式嗎?如果沒有,你的回答就足夠了,讓我更加接近理解WPF。 – bytecode77

+0

你的意思是簡化RelativeSource部分?您可以在UserControl上分配'x:Name'並使用ElementName而不是RelativeSource。 – Clemens