2016-07-04 257 views
0

我在c#WPF MVC中有一個應用程序。我的目標是創建一個標題欄,併爲我的所有窗口調用它。C#WPF綁定自定義屬性

我創造了這個:

XAML:

<Grid x:Class="Views.TitleBarView" 
     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:Views" 
     mc:Ignorable="d" 
     Style="{DynamicResource TitleStyleGrid}" 
     x:Name="barView"> 
    <Label x:Name="labelAppName" Style="{DynamicResource TitleStyleLabel}" Content="{Binding Content, ElementName=barView}"/> 
    <Button x:Name="bttnClose" Style="{DynamicResource ButtonStyleCloseWindow}" Command="{Binding CloseCommand}"/> 
</Grid> 

C#:

public partial class TitleBarView : Grid 
{ 
    static TitleBarView() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(TitleBarView), new FrameworkPropertyMetadata(typeof(TitleBarView))); 
    } 

    public readonly static DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(string), typeof(TitleBarView), new PropertyMetadata("")); 

    public string Content 
    { 
     get { return (string)GetValue(ContentProperty); } 
     set { SetValue(ContentProperty, value); } 
    } 


    public TitleBarView() 
    { 
     InitializeComponent(); 
     TitleBarViewModel tvm = new TitleBarViewModel(); 
     tvm.RequestClose += (s, e) => this.Close(); 
     DataContext = tvm; 
    } 

    private void Close() 
    { 
      Window.GetWindow(this).Close(); 
    } 
} 

我創建了財產ContentGridlabel內綁定該屬性。所以當我打電話給我的課TitleBarView我只需要設置屬性「內容」和標籤自動更新。

它的工作原理很好,當我直接將內容與字符串:

<Window [...] 
    xmlns:local="clr-namespace:VectorReaderV3.Views" 
    [...]> 
    <local:TitleBarView x:Name="titleBar" Content="My Title"/> 
<Window/> 

但隨着綁定,我有一個空標題:

<Window [...] 
    xmlns:local="clr-namespace:VectorReaderV3.Views" 
    [...]> 
    <local:TitleBarView x:Name="titleBar" Content="{Binding WindowTitle}"> 
<Window/> 

我是怎麼做了?

+0

這個'Content =「{Binding WindowTitle}」'從哪裏來? – lokusking

+3

這是爲什麼你永遠不應該顯式設置自定義控件的DataContext的標準示例(就像你在TitleBarView構造函數中那樣)。這樣做有效地避免了繼承一個DataContext,這是你在編寫Content =「{Binding WindowTitle}」時隱含的期望。 – Clemens

+0

我已經學會如此設置DataContext,最好的方法是什麼? –

回答

0

在您的代碼中,您將TitleBarView的數據上下文設置爲在代碼後面創建的TitleBarViewModel。這意味着「WindowTitle」屬性必須位於TitleBarViewModel上(我猜測它不是?)。

您不能通過從UserControl繼承來製作標準控件的方式來製作自定義控件。原因在於,在創建自定義控件時,您希望用戶創建視圖模型並提供datacontext,因此您無法在後面的代碼中創建它。

它涉及到更多的工作,但它歸結爲:

  • 樣式定義如何控制外觀,而且它必須位於ResourceDictionary中,它被定義在/從主題包括: /Generic.xaml文件(是的那個特定的位置)。該樣式必須具有與代碼隱藏文件的名稱匹配的TargetType。
  • 文件後面的代碼繼承自UI類(在您的情況下爲網格),並使用上面的代碼覆蓋默認樣式 - 就像您所做的那樣。
  • 該樣式可以使用特定的TemplateBinding綁定到代碼隱藏文件上的屬性。
  • 如果後面的代碼需要訪問樣式中的命名元素,則必須使用GetTemplateChild(「NameOfElement」)查找它們 - 這通常是在將ApplyTemplate覆蓋到例如連接按鈕事件句柄。

繼承人這也解釋了它一點更詳細的教程:http://www.wpftutorial.net/howtocreateacustomcontrol.html

如果要修改現有的控制同樣的過程適用。

0

更改Content="{Binding Content, ElementName=barView}"Content="{Binding Content, RelativeSource={RelativeSource AncestorType=local:TitleBarView}}}"並告訴發生了什麼。

+0

我已經嘗試過,但沒有任何區別 –

0

我必須修改其使用視圖模型我TitleBarView

public class MessageBoxViewModel : ViewModelBase 
{ 
    protected String windowTitle; 

    public String WindowTitle { 
    get { return windowTitle; } 
    set { windowTitle = value; OnPropertyChanged("WindowTitle"); } } 
} 

與相關視圖:

C#:

public partial class MessageBoxView : Window 
{ 
    private MessageBoxView() 
    { 
     InitializeComponent(); 
     MessageBoxViewModel dvm = new MessageBoxViewModel(); 
     dvm.PropertyChanged += (s, e) => this.PropertyChanged(s,e); 
     DataContext = dvm; 
    } 

    private void PropertyChanged(object e, PropertyChangedEventArgs s) 
    { 
     if (s.PropertyName == "WindowTitle") 
     { 
      titleBar.Content = (DataContext as MessageBoxViewModel).WindowTitle; 
     } 
    } 
} 

XAML:

<Window Title="MessageBoxView" 
    Style="{DynamicResource WindowStyle}"> 

    <local:TitleBarView x:Name="titleBar" Content="{Binding WindowTitle}"/> 
/> 

它瓦特orks,但我不確定它尊重模式MVC。這是我的第一個MVC應用程序,我非常困惑。