C# 用户控件与主窗口之间的关系
我如何才能从C# 用户控件与主窗口之间的关系,c#,wpf,binding,user-controls,C#,Wpf,Binding,User Controls,我如何才能从UserControl和父级main窗口(以及反之亦然)访问数据/属性?例如,假设我在main窗口中有一个名为mainTextBox的TextBox。然后我用另一个名为ucTextBox的TextBox创建一个UserControl。我在UserControl中还有一个名为ucButton的按钮,它应该弹出一个MessageBox,其中包含值mainTextBox.Text*ucTextBox.Text(转换为双精度,以使其工作) 我真正想知道的是如何动态地实现这一点,通过一个按钮,
UserControl
和父级main窗口(以及反之亦然)访问数据/属性?例如,假设我在main窗口中有一个名为mainTextBox
的TextBox
。然后我用另一个名为ucTextBox
的TextBox
创建一个UserControl
。我在UserControl
中还有一个名为ucButton
的按钮,它应该弹出一个MessageBox
,其中包含值mainTextBox.Text*ucTextBox.Text
(转换为双精度,以使其工作)
我真正想知道的是如何动态地实现这一点,通过一个按钮,可以创建更多能够与父级交互的UserControls
。在这种情况下,命名每个UserControl
是没有意义的
我尝试了几种方法,主要是使用get、set属性,但没有达到预期的效果。
我不确定我是否需要使用UserControl
,但我似乎已经读到,CustomControl
用于深度定制,但我不需要。这里只是一个简单的示例,让您开始使用(可能是@Adriano先生的意思):
RootViewModel.cs:
public class RootViewModel :INotifyPropertyChanged
{
#region Implementation of INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged = delegate {};
private void OnPropertyChanged(string propertyName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
private double _x;
private double _y;
public double X
{
get { return _x; }
set
{
_x = value;
OnPropertyChanged("X");
}
}
public double Y
{
get { return _y; }
set
{
_y = value;
OnPropertyChanged("Y");
}
}
public double XY
{
get { return _x * _y; }
}
}
<UserControl x:Class="WpfApplication2.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:DesignWidth="200">
<Grid>
<GroupBox Header="User Control">
<StackPanel>
<Label Content="Y:" />
<TextBox Text="{Binding Path=Y, UpdateSourceTrigger=PropertyChanged, FallbackValue=1}" Margin="5" />
<Button Content="Press me" Click="OnButtonClick" />
</StackPanel>
</GroupBox>
</Grid>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
private void OnButtonClick(object sender, RoutedEventArgs e)
{
var viewModel = (RootViewModel)DataContext;
var resultMessage = string.Format("{0} * {1} = {2}", viewModel.X, viewModel.Y, viewModel.XY);
MessageBox.Show(resultMessage, "X * Y");
}
}
UserControl1.xaml:
public class RootViewModel :INotifyPropertyChanged
{
#region Implementation of INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged = delegate {};
private void OnPropertyChanged(string propertyName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
private double _x;
private double _y;
public double X
{
get { return _x; }
set
{
_x = value;
OnPropertyChanged("X");
}
}
public double Y
{
get { return _y; }
set
{
_y = value;
OnPropertyChanged("Y");
}
}
public double XY
{
get { return _x * _y; }
}
}
<UserControl x:Class="WpfApplication2.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:DesignWidth="200">
<Grid>
<GroupBox Header="User Control">
<StackPanel>
<Label Content="Y:" />
<TextBox Text="{Binding Path=Y, UpdateSourceTrigger=PropertyChanged, FallbackValue=1}" Margin="5" />
<Button Content="Press me" Click="OnButtonClick" />
</StackPanel>
</GroupBox>
</Grid>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
private void OnButtonClick(object sender, RoutedEventArgs e)
{
var viewModel = (RootViewModel)DataContext;
var resultMessage = string.Format("{0} * {1} = {2}", viewModel.X, viewModel.Y, viewModel.XY);
MessageBox.Show(resultMessage, "X * Y");
}
}
MainWindow.xaml:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WpfApplication21="clr-namespace:WpfApplication2"
Title="Main Window" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel>
<Label Content="X:" />
<TextBox Text="{Binding Path=X, UpdateSourceTrigger=PropertyChanged, FallbackValue=1}" Margin="5" Height="24" />
</StackPanel>
<WpfApplication21:UserControl1 Grid.Row="1" Margin="5" />
</Grid>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new RootViewModel
{
X = 5,
Y = 7
};
}
}
用一个模型。主窗体将读/写模型中的(double)属性,每个用户控件将访问该属性进行读取。看看(在你的情况下,你甚至不需要数据模板)。这太棒了!但是,由于我对ViewModels这个世界非常陌生,DataContext=new RootViewModel到底做了什么?顺便问一下,这个例子是否适合插入更多的用户控件并独立工作?如果我插入另一个控件,因为它绑定到Y,所有UserControls都显示相同的值。谢谢。简言之,WPF中的所有可见元素都有一个特殊属性——DataContext,它可以包含任何对象,您可以从中获取(或设置!)数据,这些数据在xaml中具有特殊语法,称为数据绑定。在很长一段时间内(但非常重要!)您应该阅读更多关于WPF中数据绑定概念的内容。这里是一个很好的起点——对于更多用户控件的适应性来说——当然是的,但如何做到这一点取决于您到底想要实现什么。