WPF 链绑定

WPF Chain Binding(WPF 链绑定)
本文介绍了WPF 链绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想像这样进行链式绑定:我在一个窗口内有一个具有依赖属性的用户控件,该窗口具有类似的依赖属性.我想将usercontrol的dependencyproperty绑定到window的dependencyproperty.

I want to make a chain binding like this: I have a usercontrol with a dependencyproperty inside a window with similar dependencyproperty. I want to bind the dependencyproperty of the usercontrol to the dependencyproperty of the window.

我创建了一个示例项目来演示我的问题:

I created a sample project to demonstrate my problem:

UserControl1 XAML:

UserControl1 XAML:

<UserControl x:Class="WpfApplication1.UserControl1"
             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" 
             mc:Ignorable="d"
             d:DesignHeight="300" d:DesignWidth="300" DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Grid>
        <Label Content="{Binding Caption}"/>
    </Grid>
</UserControl>

UserControl1 C#:

UserControl1 C#:

public partial class UserControl1 : UserControl
  {
    public static readonly DependencyProperty CaptionProperty = DependencyProperty.Register("Caption", typeof(string), typeof(UserControl1));
    public string Caption
    {
      get { return (string)GetValue(CaptionProperty); }
      set { SetValue(CaptionProperty, value); }
    }

    public UserControl1()
    {
      InitializeComponent();
    }
  }

主窗口 XAML:

<Window xmlns:WpfApplication1="clr-namespace:WpfApplication1"  x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Label Content="{Binding Caption, Mode=OneWay}"/>
        <WpfApplication1:UserControl1 x:Name="uc" Caption="{Binding Caption, Mode=OneWay}"  Grid.Row="1"/>
    </Grid>
</Window>

主窗口 C#:

public partial class MainWindow : Window
  {
    public static readonly DependencyProperty CaptionProperty = DependencyProperty.Register("Caption", typeof(string), typeof(MainWindow));
    public string Caption
    {
      get { return (string)GetValue(CaptionProperty); }
      set { SetValue(CaptionProperty, value); }
    }

    public MainWindow()
    {
      InitializeComponent();
      (new Thread(() => { Thread.Sleep(2000); Dispatcher.Invoke(() => { uc.Caption = "YYY"; Caption = "XXX"; }); })).Start();
    }
  }

问题是,当我将 Caption 设置为(窗口的)XXX"时,我希望它也会通知用户控件并更新其 Caption,但事实并非如此.我想避免附加依赖属性并尽可能避免代码落后.有什么想法吗?

The thing is that when I set Caption to "XXX" (of the Window) I would expect it to also notify the usercontrol and update its Caption, but it doesn't. I would like to avoid Attached dependency properties and avoid code behind as much as possible. Any ideas?

感谢您的努力.

推荐答案

你可以创建一个用户控件...

You can create a user control along the lines of...

<UserControl x:Class="ChainBinding.CaptionGuy"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             >
    <Grid>
            <Label Name="CaptionLabel"/>
    </Grid>
</UserControl>

...并像这样使用您的依赖属性对其进行检测...

...and instrument it with your dependency property like this...

    #region Caption (DependencyProperty)
    public string Caption
    {
        get { return (string)GetValue(CaptionProperty); }
        set { SetValue(CaptionProperty, value); }
    }
    public static readonly DependencyProperty CaptionProperty =
        DependencyProperty.Register("Caption", typeof(string), typeof(CaptionGuy),
          new PropertyMetadata{PropertyChangedCallback = CaptionChanged});
    private static void CaptionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        CaptionGuy cg = d as CaptionGuy;
        if (cg != null && e.NewValue!=null)
        {
            cg.CaptionLabel.Content = e.NewValue.ToString();
        }
    }
    #endregion

然后你就可以像这样在WPF应用程序中部署它了……

Then you can deploy it in a WPF application like this...

<Grid>
    <chainBinding:CaptionGuy Caption="{Binding VmCaption}"/>
</Grid>

相应的视图模型(或代码隐藏,如果那是你的设计)看起来像这样......

And the corresponding View Model (or code-behind if that's your design) would look like this...

public class ViewModel : INotifyPropertyChanged
{
    public ViewModel()
    {
        Dispatcher dispatcher = Dispatcher.CurrentDispatcher;
        DispatcherTimer dt = new DispatcherTimer(new TimeSpan(0,0,0,5), DispatcherPriority.Normal,
            delegate
            {
                VmCaption = DateTime.Now.ToString("G");
            }, dispatcher);
        dt.Start();
    }
    private string _vmCaption;
    public string VmCaption
    {
        [DebuggerStepThrough]
        get { return _vmCaption; }
        [DebuggerStepThrough]
        set
        {
            if (value != _vmCaption)
            {
                _vmCaption = value;
                OnPropertyChanged("VmCaption");
            }
        }
    }
    #region INotifyPropertyChanged Implementation
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string name)
    {
        var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null);
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
    #endregion
}

这个例子只是每 5 秒更新一次标题.

This example just updates the caption with the time every 5 seconds.

当然,这个答案在依赖属性上使用回调,但这是一个环境实用性胜过声明式编程的问题.

Of course this answer uses a callback on the dependency property, but this is a matter where circumstantial practicality wins out over declarative programming.

这篇关于WPF 链绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)