![](/img/trans.png)
[英]TemplateBinding to DependencyProperty on a custom control not working
[英]TemplateBinding not working on INotifyPropertyChanged in WPF custom control
我最近在 WPF 中創建了一個 IconButton作為 CustomControl。 它對 DependencyProperties 使用 TemplateBinding:
圖標按鈕.cs
public class IconButton : Button
{
public static readonly DependencyProperty TextProperty;
public static readonly DependencyProperty MDL2IconCodeProperty;
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public string MDL2IconCode
{
get { return (string)GetValue(MDL2IconCodeProperty); }
set { SetValue(MDL2IconCodeProperty, value); }
}
static IconButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(IconButton),
new FrameworkPropertyMetadata(typeof(IconButton)));
TextProperty = DependencyProperty.Register("Text",
typeof(string),
typeof(IconButton),
new PropertyMetadata("Button text", OnTextChanged));
MDL2IconCodeProperty = DependencyProperty.Register("MDL2IconCode",
typeof(string),
typeof(IconButton),
new PropertyMetadata("\uf13e", OnIconTextChanged));
}
static void OnTextChanged(DependencyObject o,
DependencyPropertyChangedEventArgs e)
{
var iconButton = o as IconButton;
if (iconButton == null)
{
return;
}
string newText = e.NewValue as string;
iconButton.Text = newText;
}
static void OnIconTextChanged(DependencyObject o,
DependencyPropertyChangedEventArgs e)
{
var iconButton = o as IconButton;
if (iconButton == null)
{
return;
}
string newText = e.NewValue as string;
iconButton.MDL2IconCode = newText;
}
}
通用文件
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:UI.CustomControls">
<Style TargetType="{x:Type local:IconButton}"
BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:IconButton}">
<Button Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
Command="{TemplateBinding Command}"
CommandParameter="{TemplateBinding CommandParameter}"
CommandTarget="{TemplateBinding CommandTarget}">
<StackPanel>
<TextBlock HorizontalAlignment="Center"
Text="{TemplateBinding MDL2IconCode}"
FontFamily="Segoe MDL2 Assets"
FontSize="16"
x:Name="iconTextBlock"/>
<TextBlock HorizontalAlignment="Center"
Text="{TemplateBinding Text}"
x:Name="textTextBlock"/>
</StackPanel>
</Button>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
但它只工作了一半。 我很快意識到綁定到 DependencyProperties 僅適用於 XAML 設計器,而不適用於 ViewModel。 因此,當我在設計器中設置 Text 屬性時,它會起作用。 但是從 ViewModel 綁定到它,該屬性既不是最初設置也不是在 INotifyPropertyChanged 事件上更新。
因此,作為測試,我將 Text 屬性的 TemplateBinding 更改為
{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Text}
但它沒有幫助。
我的代碼可能有什么問題?
帶有 TemplateBinding 的 WPF 自定義控件是否支持 INotifyPropertyChanged?
問題是您以一種破壞Binding
的方式設置Text
和MDL2IconCode
新值,因此更改不會傳播到 UI。
iconButton.Text = newText;
....
iconButton.MDL2IconCode = newText;
正確的方法是使用SetCurrentValue
方法更改屬性的有效值,但現有觸發器、數據綁定和樣式將繼續工作。
static void OnTextChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
var iconButton = o as IconButton;
if (iconButton == null)
{
return;
}
string newText = e.NewValue as string;
iconButton.SetCurrentValue(TextProperty, newText);
}
static void OnIconTextChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
var iconButton = o as IconButton;
if (iconButton == null)
{
return;
}
string newText = e.NewValue as string;
iconButton.SetCurrentValue(MDL2IconCodeProperty, newText);
}
但是如果您在OnTextChanged
和OnIconTextChanged
沒有任何特殊邏輯,那么您可以擺脫PropertyChangedCallbacks
並且它仍然可以工作。
TextProperty = DependencyProperty.Register("Text",
typeof(string),
typeof(IconButton),
new PropertyMetadata("Button text"));
MDL2IconCodeProperty = DependencyProperty.Register("MDL2IconCode",
typeof(string),
typeof(IconButton),
new PropertyMetadata("\uf13e"));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.