我是wpf的新手,我想创建一个由文本块和文本框组成的简单用户控件,以便我可以重用它。但是,我真的不知道如何绑定文本块的内容,以便可以从外部设置它并公开文本框,以便它可以绑定到外部调用xaml的其他字段。
以下是我的用户控件的代码
<UserControl x:Class="WPFLib.UserControlLibs.TextBoxUsrCtrl"
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:WPFLib.UserControlLibs"
mc:Ignorable="d"
d:DesignHeight="20"
d:DesignWidth="300">
<StackPanel Orientation='Horizontal'
Width='{Binding ActualWidth, ElementName=parentElementName}'
Height='{Binding ActualWidth, ElementName=parentElementName}'>
<Grid HorizontalAlignment='Stretch'>
<Grid.ColumnDefinitions>
<ColumnDefinition Width='1*' />
<ColumnDefinition Width='1*' />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text='{Binding Text, ElementName=parentElementName}'
Background='Aqua'
Grid.Column='0'
Grid.Row='0' />
<TextBox x:Name='UserTxBox'
Grid.Column='1'
Grid.Row='0'
Background='Red'
HorizontalAlignment='Stretch'
Text='this is a test to see how it works' />
</Grid>
</StackPanel>
</UserControl>
如何从TextBlock和TextBox中公开Text,以便可以从调用xaml中设置和检索它?
例如
<Window x:Class="TestWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TestWPF"
xmlns:controls='clr-namespace:WPFLib.UserControlLibs'
` mc:Ignorable="d"
Title="MainWindow"
Height="350"
Width="525"
WindowState='Maximized'
FontSize='18'>
<StackPanel>
<controls:TextBoxUsrCtrl Width='500' HorizontalAlignment='Left' **Text='NEED TO SET THE TEXT BLOCK HERE'**/>
</StackPanel>
</Window>
答案 0 :(得分:3)
你应该给它两个依赖属性,一个用于你想要公开的两个文本属性中的每一个(这是一个非常大量的样板;我使用Visual Studio的片段功能来生成所有这些)。然后在UserControl XAML中,将控件属性绑定到这些属性。
public partial class TextBoxUsrCtrl : UserControl
{
public TextBoxUsrCtrl()
{
InitializeComponent();
}
#region Text Property
public String Text
{
get { return (String)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(nameof(Text), typeof(String), typeof(TextBoxUsrCtrl),
new FrameworkPropertyMetadata(null) {
// It's read-write, so make it bind both ways by default
BindsTwoWayByDefault = true
});
#endregion Text Property
#region DisplayText Property
public String DisplayText
{
get { return (String)GetValue(DisplayTextProperty); }
set { SetValue(DisplayTextProperty, value); }
}
public static readonly DependencyProperty DisplayTextProperty =
DependencyProperty.Register(nameof(DisplayText), typeof(String), typeof(TextBoxUsrCtrl),
new PropertyMetadata(null));
#endregion DisplayText Property
}
XAML。我简化了这个,所以布局按照我的意思运作。
注意绑定如何使用RelativeSource={RelativeSource AncestorType=UserControl}
绑定到我们在UserControl
上面定义的依赖项属性。默认情况下,Binding
会绑定到UserControl.DataContext
的属性,但我们不会使用它。原因是如果我们在这里设置UserControl.DataContext
,那将在本答案结尾处打破最终XAML片段中的viewmodel属性绑定。这些绑定将在我们的控件上查找这些属性。有解决方法,但它变得丑陋。我在这里完成它的方式是最好的,因为它永远不会破坏任何人对DataContext
继承的假设。
<UserControl
x:Class="WPFLib.UserControlLibs.TextBoxUsrCtrl"
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:WPFLib.UserControlLibs"
mc:Ignorable="d"
d:DesignHeight="20"
d:DesignWidth="300"
>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width='*' />
<ColumnDefinition Width='*' />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock
Text='{Binding DisplayText, RelativeSource={RelativeSource AncestorType=UserControl}}'
Background='Aqua'
Grid.Column='0'
Grid.Row='0'
/>
<TextBox
x:Name='UserTxBox'
Grid.Column='1'
Grid.Row='0'
Background='Red'
HorizontalAlignment='Stretch'
Text='{Binding Text, RelativeSource={RelativeSource AncestorType=UserControl}}'
/>
</Grid>
</UserControl>
在窗口中使用,绑定到viewmodel属性:
<local:TextBoxUsrCtrl
Text="{Binding TestText}"
DisplayText="{Binding ShowThisText}"
/>
最后,我不确定您使用ElementName=parentElementName
获得了什么。如果这意味着是对父母控制的引用,那么你就无法做到,如果可以的话,这不是一个好主意。您不希望UserControl
受到父控件必须具有特定名称的要求的约束。该要求的答案很简单,XAML中的控件只负责如果它们具有固定大小的自身大小。如果它们的大小应该是父母的大小,那么父母总是对此负责。因此,如果您想将两个TextBoxUsrCtrl
实例的大小设置为两个不同的父母,那很好。每个父母都可以随意选择自己的孩子。