2011-01-25 22 views
2

InnerCaptionというプロパティを公開するWPFユーザーコントロールを作成したいとします。コードはWPFバインドの問題

以下の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> 

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)); 
     } 
} 

の背後にあるCSコード質問があるある:私は、ユーザーが設計時にInnerCaptionをカスタマイズできるようにしたいですその色、フォントスタイルを変更するなど...しかし、私は束縛のいくつかの種類を使用しようとしました。しかし、それは無駄です。私が知っているように、Bindingはプロパティへのバインドのみをサポートしています。 私に方法を教えてくださいpls! :(

答えて

0

上記の私の問題を解決する簡単な方法があります:ContentPresenterコントロールの使い方はどうですか?あなたのプロパティ(TextBlock、string、...)を宣言し、そのコントロールにプロパティをバインドするコード行。私は試して、それは動作します! :D

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 
} 

これがあなたを助けてくれることを願っています!

EDIT:

が、私は通常、基本クラスでINotifyPropertyChangedのものを実装する「NotifyPropertyChangedBase:

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 
    } 
+0

私はINotifyPropertyChangedインターフェイスを1分で追加します...ちょうど仕事に着いたので、いくつかのものを整理する必要があります。 – Christian

+0

これは、INotifyPropertyChanged -patternを実装した適切なモデルで単純なバインディングを使用する方法の優れた例ですが、要求されたようにキャプションのスタイルをバインドできる方法の問題を解決しません。スタイル " – Almund

+0

あなたは、テキストキャプションのようにfore/backgroundのカラープロパティをバインドできます。 "MyClassToBind"クラスを使用すると、コントロールの任意のプロパティをバインドできます。それとも、私はその質問を誤解しましたか? – Christian

1

私が何をした後かもしれませんが、おそらくサブクラス化のラインでより多くの何かだと思いますそのコントロールの既存のプロパティを簡単に利用できるようにするTextBlock。

public class MyCaptionControl : TextBlock 
{ 
.... 
} 

これは、あなたが通常どおりにバインドすることができます:

<MyCaptionControl FontSize="{Binding MyModelSize}" Text="{Binding MyModelCaption}" /> 

You're間違いなく依存関係プロパティを作成し、正しい方向ではなく、あなたがyou'llは、バインド可能な値ごとに一つの特性を必要とし、これらのプロパティにバインドしたい場合。同様

public static readonly DependencyProperty ForegroundColor = .... 
public static readonly DependencyProperty BackgroundColor = .... 

これらは、直接ユーザーコントロール内の任意の内部のTextBlockコントロールにマップすることができますが、私が述べたように、私はあなたがサブクラス化のTextBlockの方が良いと思います。

+0

あなたの答えをありがとう! :) – anhldbk