将 属性 与用户控件拥有的另一个 属性 绑定
Binding a property with another property owned to a user control
我想实现几个属性之间的绑定。可能吗?
我有一个名为 "MainWindow" 的主 window class,它拥有一个 属性 "InputText"。此 class 包含一个名为 MyUserControl 的用户控件。 MyUserControl 有一个绑定到依赖项的文本框 属性 "MyTextProperty"
我想将我的主要 window 的 属性 "InputText" 与我的用户控件的依赖项 属性 "MyTextProperty" 绑定。因此,如果用户编写文本,我希望更新属性 "InputText"、"MyTextProperty"、"MyText"。
用户控制码:
using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MyUserControl.xaml
/// </summary>
public partial class MyUserControl : UserControl
{
public string MyText
{
get { return (string)GetValue(MyTextProperty); }
set { SetValue(MyTextProperty, value); }
}
public static readonly DependencyProperty MyTextProperty =
DependencyProperty.Register("MyText", typeof(string), typeof(MyUserControl), new PropertyMetadata(0));
public MyUserControl()
{
this.DataContext = this;
InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string property)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(property));
}
}
}
}
WPF用户控件代码:
<UserControl x:Class="WpfApplication1.MyUserControl"
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="25 " d:DesignWidth="100"
Background="Black">
<Grid>
<TextBox Height="20" Width="100" Text="{Binding MyText}"></TextBox>
</Grid>
</UserControl>
主要window代码:
using System;
using System.Linq;
using System.Windows;
using System.ComponentModel;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
private string inputText;
public string InputText
{
get { return inputText; }
set
{
inputText = value;
NotifyPropertyChanged("InputText");
}
}
public MainWindow()
{
this.DataContext = this;
InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String property)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(property));
}
}
}
}
WPF 主要 window 代码:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myNS="clr-namespace:WpfApplication1"
Title="MainWindow" Height="80" Width="300">
<Grid>
<StackPanel Orientation="Vertical">
<myNS:MyUserControl x:Name="test" MyText="{Binding InputText}"></myNS:MyUserControl>
<Button Name="cmdValidation" Content="Validation" Height="20"></Button>
</StackPanel>
</Grid>
</Window>
谢谢!
首先,
this.DataContext = this;
没有。就是不行。您正在覆盖其父项 window 设置的 UserControl
的 DataContext
。
对于你的UserControl
,给它一个x:Name
,并直接绑定到依赖项属性。
<UserControl
...
x:Name="usr">
<TextBox Text="{Binding MyText, ElementName=usr}" ... />
完成后,您可以简单地将 MyText
属性 绑定到 MainWindow
的 DataContext
。
<myNS:MyUserControl x:Name="test" MyText="{Binding InputText}" />
如果您希望发布的代码尽可能少地更改,那么:
在MainWindow.xaml中,更改
MyText="{Binding InputText}"
到
MyText="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.InputText, Mode=TwoWay}"
如果你想让 UC 更新 InputText,你需要 TwoWay。
此外,在 MyUserControl.xaml.cs 中,在您的 DependencyProperty.Register 语句中,您将字符串的 PropertyMetadata 默认值设置为 0 - 将其更改为适合字符串的值 - 例如 null 或 string.empty.
public static readonly DependencyProperty MyTextProperty =
DependencyProperty.Register("MyText", typeof(string), typeof(MyUserControl), new PropertyMetadata(null));
如果您想稍微更改代码,可以在用户控件中使其更复杂,但在使用时更简单:
建立依赖关系属性,MyText,默认绑定两种方式
停止在用户控件中设置 DataContext
更改 UC xaml 文本绑定以使用 UC
的相对来源
我总是觉得代码更容易理解,所以这里是你的文件的修改版本:
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myNS="clr-namespace:WpfApplication1"
Title="MainWindow" Height="180" Width="300">
<Grid>
<StackPanel Orientation="Vertical">
<TextBlock>
<Run Text="MainWindow.InputText: " />
<Run Text="{Binding InputText}" />
</TextBlock>
<TextBlock>
<Run Text="MyUserControl.MyText: " />
<Run Text="{Binding ElementName=test, Path=MyText}" />
</TextBlock>
<myNS:MyUserControl x:Name="test" MyText="{Binding InputText}"></myNS:MyUserControl>
<Button Name="cmdValidation" Content="Validation" Height="20"></Button>
</StackPanel>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Windows;
using System.ComponentModel;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
private string inputText = "Initial Value";
public string InputText
{
get { return inputText; }
set
{
inputText = value;
NotifyPropertyChanged("InputText");
}
}
public MainWindow()
{
this.DataContext = this;
InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String property)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(property));
}
}
}
}
MyUserControl.xaml
<UserControl x:Class="WpfApplication1.MyUserControl"
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="25 " d:DesignWidth="100"
Background="Black">
<Grid>
<TextBox Height="20" Width="100" Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=MyText, UpdateSourceTrigger=PropertyChanged}"></TextBox>
</Grid>
</UserControl>
MyUserControl.xaml.cs
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MyUserControl.xaml
/// </summary>
public partial class MyUserControl : UserControl
{
public string MyText
{
get { return (string)GetValue(MyTextProperty); }
set { SetValue(MyTextProperty, value); }
}
public static readonly DependencyProperty MyTextProperty =
DependencyProperty.Register("MyText", typeof(string), typeof(MyUserControl), new FrameworkPropertyMetadata(null) { BindsTwoWayByDefault = true });
public MyUserControl()
{
InitializeComponent();
}
}
}
我想实现几个属性之间的绑定。可能吗?
我有一个名为 "MainWindow" 的主 window class,它拥有一个 属性 "InputText"。此 class 包含一个名为 MyUserControl 的用户控件。 MyUserControl 有一个绑定到依赖项的文本框 属性 "MyTextProperty"
我想将我的主要 window 的 属性 "InputText" 与我的用户控件的依赖项 属性 "MyTextProperty" 绑定。因此,如果用户编写文本,我希望更新属性 "InputText"、"MyTextProperty"、"MyText"。
用户控制码:
using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MyUserControl.xaml
/// </summary>
public partial class MyUserControl : UserControl
{
public string MyText
{
get { return (string)GetValue(MyTextProperty); }
set { SetValue(MyTextProperty, value); }
}
public static readonly DependencyProperty MyTextProperty =
DependencyProperty.Register("MyText", typeof(string), typeof(MyUserControl), new PropertyMetadata(0));
public MyUserControl()
{
this.DataContext = this;
InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string property)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(property));
}
}
}
}
WPF用户控件代码:
<UserControl x:Class="WpfApplication1.MyUserControl"
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="25 " d:DesignWidth="100"
Background="Black">
<Grid>
<TextBox Height="20" Width="100" Text="{Binding MyText}"></TextBox>
</Grid>
</UserControl>
主要window代码:
using System;
using System.Linq;
using System.Windows;
using System.ComponentModel;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
private string inputText;
public string InputText
{
get { return inputText; }
set
{
inputText = value;
NotifyPropertyChanged("InputText");
}
}
public MainWindow()
{
this.DataContext = this;
InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String property)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(property));
}
}
}
}
WPF 主要 window 代码:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myNS="clr-namespace:WpfApplication1"
Title="MainWindow" Height="80" Width="300">
<Grid>
<StackPanel Orientation="Vertical">
<myNS:MyUserControl x:Name="test" MyText="{Binding InputText}"></myNS:MyUserControl>
<Button Name="cmdValidation" Content="Validation" Height="20"></Button>
</StackPanel>
</Grid>
</Window>
谢谢!
首先,
this.DataContext = this;
没有。就是不行。您正在覆盖其父项 window 设置的 UserControl
的 DataContext
。
对于你的UserControl
,给它一个x:Name
,并直接绑定到依赖项属性。
<UserControl
...
x:Name="usr">
<TextBox Text="{Binding MyText, ElementName=usr}" ... />
完成后,您可以简单地将 MyText
属性 绑定到 MainWindow
的 DataContext
。
<myNS:MyUserControl x:Name="test" MyText="{Binding InputText}" />
如果您希望发布的代码尽可能少地更改,那么:
在MainWindow.xaml中,更改
MyText="{Binding InputText}"
到
MyText="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.InputText, Mode=TwoWay}"
如果你想让 UC 更新 InputText,你需要 TwoWay。
此外,在 MyUserControl.xaml.cs 中,在您的 DependencyProperty.Register 语句中,您将字符串的 PropertyMetadata 默认值设置为 0 - 将其更改为适合字符串的值 - 例如 null 或 string.empty.
public static readonly DependencyProperty MyTextProperty =
DependencyProperty.Register("MyText", typeof(string), typeof(MyUserControl), new PropertyMetadata(null));
如果您想稍微更改代码,可以在用户控件中使其更复杂,但在使用时更简单:
建立依赖关系属性,MyText,默认绑定两种方式
停止在用户控件中设置 DataContext
更改 UC xaml 文本绑定以使用 UC
的相对来源我总是觉得代码更容易理解,所以这里是你的文件的修改版本: MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myNS="clr-namespace:WpfApplication1"
Title="MainWindow" Height="180" Width="300">
<Grid>
<StackPanel Orientation="Vertical">
<TextBlock>
<Run Text="MainWindow.InputText: " />
<Run Text="{Binding InputText}" />
</TextBlock>
<TextBlock>
<Run Text="MyUserControl.MyText: " />
<Run Text="{Binding ElementName=test, Path=MyText}" />
</TextBlock>
<myNS:MyUserControl x:Name="test" MyText="{Binding InputText}"></myNS:MyUserControl>
<Button Name="cmdValidation" Content="Validation" Height="20"></Button>
</StackPanel>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Windows;
using System.ComponentModel;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
private string inputText = "Initial Value";
public string InputText
{
get { return inputText; }
set
{
inputText = value;
NotifyPropertyChanged("InputText");
}
}
public MainWindow()
{
this.DataContext = this;
InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String property)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(property));
}
}
}
}
MyUserControl.xaml
<UserControl x:Class="WpfApplication1.MyUserControl"
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="25 " d:DesignWidth="100"
Background="Black">
<Grid>
<TextBox Height="20" Width="100" Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=MyText, UpdateSourceTrigger=PropertyChanged}"></TextBox>
</Grid>
</UserControl>
MyUserControl.xaml.cs
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MyUserControl.xaml
/// </summary>
public partial class MyUserControl : UserControl
{
public string MyText
{
get { return (string)GetValue(MyTextProperty); }
set { SetValue(MyTextProperty, value); }
}
public static readonly DependencyProperty MyTextProperty =
DependencyProperty.Register("MyText", typeof(string), typeof(MyUserControl), new FrameworkPropertyMetadata(null) { BindsTwoWayByDefault = true });
public MyUserControl()
{
InitializeComponent();
}
}
}