2016-07-04 214 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应用程序,我非常困惑。