我想创建一个WPF用户控件,公开一个名为InnerCaption的属性。代码在
之下XAML代码
<UserControl x:Class="myControl.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<TextBlock Name="_innerCaption" > Hello</TextBlock>
</Grid>
</UserControl>
CS代码
namespace myControl
{
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public TextBlock InnerCaption
{
get { return (TextBlock)this.GetValue(InnerCaptionProperty); }
set { this.SetValue(InnerCaptionProperty, value); }
}
public static readonly DependencyProperty InnerCaptionProperty = DependencyProperty.Register(
"InnerCaption", typeof(TextBlock), typeof(UserControl1),new PropertyMetadata(false));
}
}
问题是:我希望用户能够在设计时自定义InnerCaption,例如:修改其颜色,字体样式......但我不知道叹了口气使用某种Binding。但这是徒劳的。据我所知,Binding仅支持绑定到属性,对吧? 给我看一个方法! :(
答案 0 :(得分:1)
绑定如下所示:
XAML
<UserControl x:Class="myControl.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<TextBlock Name="_innerCaption"
Text="{Binding MyCaption}"/>
</Grid>
</UserControl>
现在您必须将XAML文件的DataContext设置为您要绑定到的类:
namespace myControl
{
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl
{
MyClassToBindTo bindingClass;
public UserControl1()
{
InitializeComponent();
bindingClass = new MyClassToBindTo();
DataContext = bindingClass;
}
}
}
绑定类可能如下所示:
public class MyClassToBindTo : NotifyPropertyChangedBase
{
private string myCaptionString = "hello";
public string MyCaption
{
get { return myCaptionString }
set { myCaptionString = value; OnPropertyChanged("MyCaptionString"); }
}
// Also implement the INotifyPropertyChanged interface here
}
希望这能帮到你!
修改强>
我通常在基类“NotifyPropertyChangedBase:
中实现INotifyPropertyChanged内容public abstract class PropertyChangedBase : INotifyPropertyChanged
{
#region Member Variables
private static HashSet<string> alreadyCoveredProperties = new HashSet<string>();
#endregion
#region INotifyPropertyChanged Members
/// <summary>
/// Occurs when a property value changes.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Calls registered handlers when a property is changed.
/// </summary>
/// <param name="propertyName">Name of the property.</param>
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
/// <summary>
/// Removes all property changed subscription from the event handler.
/// </summary>
protected void RemovePropertyChangedSubscription()
{
if (this.PropertyChanged != null)
{
this.PropertyChanged -= new PropertyChangedEventHandler(PropertyChanged);
this.PropertyChanged = null;
}
}
/// <summary>
/// Determines whether the specified property name refers to a property defined for this object.
/// </summary>
/// <param name="propertyName">Name of the property.</param>
/// <returns>
/// Returns <c>true</c> if the provided name refers to a defined property; otherwise, <c>false</c>.
/// </returns>
/// <remarks>Uses reflection.</remarks>
protected bool IsDefinedPropertyName(string propertyName)
{
string propertyFullName = GetType().FullName + "." + propertyName;
if (alreadyCoveredProperties.Contains(propertyFullName))
{
return true;
}
else
{
PropertyDescriptorCollection col = TypeDescriptor.GetProperties(this);
PropertyDescriptor propertyDescriptor = col[propertyName];
// A property exists, if the propertyDescriptor is != null.
if (propertyDescriptor != null)
{
alreadyCoveredProperties.Add(propertyFullName);
return true;
}
else
{
return false;
}
}
}
#endregion
}
答案 1 :(得分:1)
我认为你可能会想到的可能是对TextBlock进行子类化的更多内容,这将允许您轻松地使用该控件上的现有属性。
public class MyCaptionControl : TextBlock
{
....
}
这使您可以像平常一样进行绑定:
<MyCaptionControl FontSize="{Binding MyModelSize}" Text="{Binding MyModelCaption}" />
你肯定是在正确的方向创建一个依赖属性,但如果你想绑定到这些属性,你需要每个可绑定值一个属性。像
public static readonly DependencyProperty ForegroundColor = ....
public static readonly DependencyProperty BackgroundColor = ....
然后可以将这些直接映射到用户控件中的任何内部文本块控件,但正如我所提到的,我认为你会更好地继承TextBlock。
答案 2 :(得分:0)
上面的问题有一个简单的解决方案:如何使用ContentPresenter控件?只需几行代码声明您的属性(TextBlock,string,...),然后将控件绑定到属性。我试过了,它的确有效! :D