Sha*_*awn 2 c# data-binding wpf xaml
我有一个自定义TextBox控件.我试图将它绑定到对象的简单描述字符串属性.如何让绑定工作?如果我将其更改为TextBox,相同的绑定工作正常.
<Style x:Key="{x:Type TaskDash:TextBoxWithDescription}" TargetType="{x:Type TaskDash:TextBoxWithDescription}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TaskDash:TextBoxWithDescription}">
<TextBox>
</TextBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Run Code Online (Sandbox Code Playgroud)
public class TextBoxWithDescription : TextBox
{
public TextBoxWithDescription()
{
LabelText = String.Empty;
}
public string LabelText { get; set; }
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var textBlock = (TextBlock)this.Template.FindName("LabelText", this);
if (textBlock != null) textBlock.Text = this.LabelText;
}
}
Run Code Online (Sandbox Code Playgroud)
<TaskDash:TextBoxWithDescription Grid.Row="0" Grid.Column="0"
x:Name="textBoxDescription"
Text="{Binding Description, BindsDirectlyToSource=True}" LabelText="Description">
</TaskDash:TextBoxWithDescription>
Run Code Online (Sandbox Code Playgroud)
public partial class EditTaskItem : Window
{
private TaskItem _taskItem;
public EditTaskItem(TaskItem taskItem)
{
InitializeComponent();
this.DataContext = taskItem;
textBoxDescription.DataContext = taskItem;
_taskItem = taskItem;
}
}
Run Code Online (Sandbox Code Playgroud)
好的......您的代码有一些问题.让我们从您的自定义控件的样式开始.您需要添加一个静态构造函数,以允许重新设置新控件.像这样
static TextBoxWithDescription ()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(TextBoxWithDescription ), new FrameworkPropertyMetadata(typeof(TextBoxWithDescription )));
}
Run Code Online (Sandbox Code Playgroud)
这告诉WPF"嘿,请为此控件寻找样式".
现在您可以删除它,x:Key="{x:Type TaskDash:TextBoxWithDescription}"因为这将是您的默认样式.
接下来是.在WPF中,要理解的是,每个控件都绝对没有UI内容,除非它获得模板.您的Style中已经有一个模板,但它获得的唯一可视内容是一个空的TextBox.这很奇怪,因为您从TextBox派生了TextBoxWithDescription.所以你创建的是一个从文本框派生的控件,包含一个文本框.请参阅此内容以查看TextBox模板在WPF 4.0中的外观.
返回ControlTemplate中的空TextBox.请记住,我说,你的控件,没有风格是完全看不见的,它唯一的逻辑.唯一可见的是模板中的TextBox.为了使它以某种方式工作,您需要将一些属性传递给此TextBox.控件说明了如何以及模板获取属性并将其置于使用中.你可以通过TemplateBinding
例如这样做.如果您的控件具有属性背景,则只要您愿意,此属性不会执行任何操作,但ControlTemplate可以为其赋予一些含义.例如,Rectangle在您的中添加一个ControlTemplate并将Fill Property设置为{TemplateBinding Background}.哪个基本告诉Rectangle"你的属性填充将是我们目前模板控件的背景值".我希望这说清楚.
接下来:你覆盖了OnApplyTemplate你通常这样做是为了在你的ControlTemplate中按名称查找一个控件.您似乎将此与您的某个属性混合在一起.要通过FindName在模板中查找控件,您需要为其命名
像这样
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TaskDash:TextBoxWithDescription}">
<TextBox x:Name="PART_MyTextBox">
</TextBox>
</ControlTemplate>
</Setter.Value>
</Setter>
Run Code Online (Sandbox Code Playgroud)
并将OnApplyTemplate修改为
var textBlock = (TextBlock)this.Template.FindName("PART_MyTextBox", this);
Run Code Online (Sandbox Code Playgroud)
现在,您在当前的ControlTemplate中拥有了文本块.
我能看到的最后一个错误是.您在OnApplyTemplateTextBox文本中设置LabelText.虽然这有效,但有一次,它不是很好,通常不是WPF方式.此外,如果您修改LabelText属性,它将不会显示,因为您必须再次设置它.将LabelText更改为依赖项属性现在,您可以使用已经提到的TemplateBinding内容直接在控件模板TextBox上设置此文本.
<TextBox x:Name="PART_MyTextBox" Text="{TemplateBinding LabelText}>
</TextBox>
Run Code Online (Sandbox Code Playgroud)
这还将确保对Control属性的更改也将更新此TextBox上的Text.
最后一件事
this.DataContext = taskItem;
// textBoxDescription.DataContext = taskItem;
_taskItem = taskItem;
Run Code Online (Sandbox Code Playgroud)
如果您的textboxdescription将成为窗口的父级,则不需要DataContext显式设置,因为它将在层次结构中继承.只要Element不更改DataContext,它就始终是父元素的DataContext.
我建议你阅读更多关于WPF的基础知识,我知道它有一个陡峭的学习曲线,但它值得努力.如果有人来自WinForms背景,那就很难让所有不同的新设计理念和不同的做事方式得到满足.
希望那有所帮助
| 归档时间: |
|
| 查看次数: |
4199 次 |
| 最近记录: |