WPF绑定问题

时间:2011-01-25 07:14:53

标签: .net wpf binding

我想创建一个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仅支持绑定到属性,对吧? 给我看一个方法! :(

3 个答案:

答案 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