繁体   English   中英

C#WPF绑定自定义属性

[英]C# WPF binding custom property

我在c#WPF MVC中有一个应用程序。 我的目标是创建一个标题栏,并在所有窗口中调用它。

我创建了这个:

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

我已经为Grid创建了属性Content ,并且内部的label绑定了该属性。 因此,当我调用类TitleBarView我只需要设置属性“ Content”,标签就会自动更新。

当我直接使用String设置内容时,它会很好地工作:

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

我做错了什么?

Content="{Binding Content, ElementName=barView}"更改为Content="{Binding Content, RelativeSource={RelativeSource AncestorType=local:TitleBarView}}}"并告诉会发生什么。

我已经修改了使用我的TitleBarView的ViewModel:

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}"/>
/>

它可以工作,但我不确定它是否尊重MVC模式。 这是我的第一个MVC应用程序,对此我感到非常困惑。

在您的代码中,将TitleBarView的数据上下文设置为在后面的代码中创建的TitleBarViewModel。 这意味着“ WindowTitle”属性必须位于TitleBarViewModel上(我猜不是吗?)。

您不能通过继承UserControl的方式来制作自定义控件,也不能像制作标准控件那样来制作自定义控件。 原因是在创建自定义控件时,您打算让用户创建视图模型并提供数据上下文,因此您无法在后面的代码中创建它。

它涉及更多的工作,但归结为:

  • 样式定义控件的外观,并且它必须位于ResourceDictionary中,该资源在Themes / Generic.xaml文件中定义/包含在该文件中(是​​该特定位置)。 样式必须具有与代码隐藏文件名称匹配的TargetType。
  • 文件后面的代码继承自一个UI类(在您的情况下为Grid),并使用上面的一种覆盖了默认样式-就像您所做的那样。
  • 样式可以使用特定的TemplateBinding绑定到文件后面代码上的属性。
  • 如果后面的代码需要访问样式中的命名元素,则必须使用GetTemplateChild(“ NameOfElement”)查找它们-这通常是在ApplyTemplate的重写中完成的,例如,挂钩按钮事件句柄。

这是一个对它进行详细解释的教程: http : //www.wpftutorial.net/howtocreateacustomcontrol.html

如果要修改现有控件,则适用相同的过程。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM