我创建了一个自定义的wpf控件,希望能够反复使用它来减少编写,复制和粘贴一堆xaml代码所花费的时间。它看起来很简单。它用于Label和TextBox对,所以:
Label here
[ this is the text box (or other control) ]
这样称呼:
<controls:LabeledContentControl Margin="5"
MaxHeight="25"
LabelText="{Binding LabelString}"
Content="{Binding LabelTextBoxTestString, ValidatesOnNotifyDataErrors=True, UpdateSourceTrigger=PropertyChanged}"/>
或
<controls:LabeledContentControl Margin="5"
LabelText="{Binding LabelString}">
<TextBox Text="{Binding LabelTextBoxTestString,
ValidatesOnNotifyDataErrors=True,
UpdateSourceTrigger=PropertyChanged,
Delay=100}" />
</controls:LabeledContentControl>
LabeledContentControl
扩展ContentControl
,c#代码似乎不相关,因为它的依赖属性及其setter。与两个构造函数类似,这些构造函数在Microsoft参考文档中实现,用于扩展ContentControl
在使用标记内容控件的第一种方法时,我遇到了绑定后备视图模型属性/字段集的问题。
控件的XAML代码如下:
<Style x:Key="{x:Type controls:LabeledContentControl}" TargetType="{x:Type controls:LabeledContentControl}">
<!-- other setters.... -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:LabeledContentControl}">
<Border Name="OuterBd" BorderThickness="{TemplateBinding BorderThickness}" >
<Border Name="InnerBd" Background="{TemplateBinding BorderBrush}" BorderThickness="0">
<Border Name="Bd" Background="{TemplateBinding Background}" BorderThickness="0">
<DockPanel>
<DockPanel DockPanel.Dock="Top" IsHitTestVisible="False">
<TextBlock x:Name="FieldRequiredInd"
Text="* "
Foreground="Red"
Visibility="Collapsed"
DockPanel.Dock="Left"/>
<TextBlock x:Name="LabelTextBlock"
DockPanel.Dock="Left"
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=LabelText, Mode=OneWay}" />
</DockPanel>
<ContentPresenter x:Name="CustomContent" DockPanel.Dock="Bottom"
Content="{TemplateBinding Content}"
ContentTemplateSelector="{StaticResource LabeledContentControlDataTemplateSelector}"
MaxHeight="{TemplateBinding MaxHeight}"/>
</DockPanel>
</Border>
</Border>
</Border>
<ControlTemplate.Triggers>
...
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
模板选择器,同样是超级基本的,如果内容属于string
类型使用GetType
,则使用字符串的自定义数据窗口,以便它们位于文本框中并可编辑。
<DataTemplate x:Key="StringDataTemplate" DataType="{x:Type system:String}">
<TextBox>
<TextBox.Text>
<Binding Path="." />
</TextBox.Text>
</TextBox>
</DataTemplate>
<local:LabeledContentControlDataTemplateSelector x:Key="LabeledContentControlDataTemplateSelector"
StringDataTemplate="{StaticResource StringDataTemplate}"/>
我如何/可以正确绑定LabelTextBoxTestString
,这样当我在StringDataTemplate
生成的文本框中更新/输入内容时,它会更新绑定属性ViewModel?目前,当我使用第一种方法时,当我输入由StringDataTemplate
创建的文本框时,后备字段不会使用新内容进行更新,但在使用第二种方法时,后备字段会更新。
答案 0 :(得分:2)
您需要进行一些修改:
首先是Binding
中的正确TextBox.Text
:
<TextBox.Text>
<Binding Path="Content" RelativeSource="{RelativeSource TemplatedParent}" UpdateSourceTrigger="PropertyChanged" />
</TextBox.Text>
然后将ContentPresenter
的绑定更改为:
<ContentPresenter x:Name="CustomContent"
MaxHeight="{TemplateBinding MaxHeight}"
Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=local:LabeledContentControl}, Path=Content, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ContentTemplateSelector="{StaticResource LabeledContentControlDataTemplateSelector}"
DockPanel.Dock="Bottom" />
现在你可以绑定你的控件了。请注意,Mode
设置为TwoWay
Content
属性(默认为OneWay
),这就是您没有得到反馈的原因:
<controls:LabeledContentControl Margin="5"
MaxHeight="25"
LabelText="{Binding LabelString}"
Content="{Binding LabelTextBoxTestString, ValidatesOnNotifyDataErrors=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>