2012-06-11 11 views
6

Sto tentando di creare un proxy di proprietà di dipendenza semplice. Ho creato un controllo personalizzato, è un raccoglitore di file, che è costituito da una casella di testo (nome: "TextBox_FilePath") e un pulsante che mostra la finestra di dialogo del file aperto.Creare un proxy per una proprietà di dipendenza

Mentre eseguo un controllo riutilizzabile mi piacerebbe avere una proprietà "SelectedFilePath". Poiché la proprietà Text sembra essere perfetta affinché il mio controllo sia la proprietà "SelectedFilePath", desidero semplicemente eseguire il proxy di queste proprietà di dipendenza.

Il primo approccio che ho fatto era:

public static readonly DependencyProperty SelectedFilePathProperty = TextBox.TextProperty; 

public string SelectedFilePath 
{ 
    get { return (string) this.TextBox_FilePath.GetValue(SelectedFilePathProperty); } 
    set { this.TextBox_FilePath.SetValue(SelectedFilePathProperty, value); } 
} 

che ha funzionato, ma gettato un'eccezione quando si cerca di legarsi a quella proprietà. Poi sono uscito con:

public static readonly DependencyProperty SelectedFilePathProperty = 
    DependencyProperty.Register("SelectedFilePath", typeof (string), typeof (FilePicker), new PropertyMetadata(default(string))); 

public string SelectedFilePath 
{ 
    get { return (string) this.TextBox_FilePath.GetValue(SelectedFilePathProperty); } 
    set { this.TextBox_FilePath.SetValue(SelectedFilePathProperty, value); } 
} 

che funziona, ma non ho idea del perché ?! Dove ho specificato che volevo la proprietà text della casella di testo?

Che cosa mi manca semplicemente proxy di proprietà di dipendenza?

EDIT: La soluzione con AddOwner non funziona troppo, viene generata Excetion dire "legame può essere applicato solo su una proprietà di dipendenza". Codice:

public static readonly DependencyProperty SelectedFilePathProperty = 
    TextBox.TextProperty.AddOwner(typeof(FilePicker)); 

public string SelectedFilePath 
{ 
    get { return (string)this.TextBox_FilePath.GetValue(SelectedFilePathProperty); } 
    set { this.TextBox_FilePath.SetValue(SelectedFilePathProperty, value); } 
} 

Cosa non capisco?

EDIT2: per tutti gli altri che hanno problemi di comprensione la risposta, ho fatto a little graphic

risposta

3

Il primo approccio non funziona perché la proprietà è registrati solo per il TextBox, l'aggiunta di un riferimento in un altro la classe non fa niente.

Il secondo crea semplicemente una proprietà di stringa completamente nuova.

Se si desidera veramente riutilizzare la chiamata AddOwnerTextBox.TextProperty.

ad es.

public static readonly DependencyProperty SelectedFilePathProperty = 
    TextBox.TextProperty.AddOwner(typeof(FilePicker)); 

(notare che questa proprietà è registrato come "Text", quindi probabilmente dovrebbe solo creare una nuova proprietà con il nome che si desidera come avete fatto già. Io consiglio anche per set metadata flags a bind two-way by default se si vuole avere la stesso comportamento vincolante come TextBox.Text.)

+0

Si prega di vedere la mia modifica :) – GameScripting

+0

* Come ho detto *, è registrato con il nome di "testo", si può quindi legarsi solo a una proprietà chiamata 'Testo', la proprietà' SelectedFilePath' che hai creato è solo un wrapper per comodità nel tuo codice imperativo, i binding non la usano mai. Registra la tua proprietà se vuoi un nome diverso. –

+0

Puoi essere così gentile e fornire un esempio o dare qualche riferimento su come farlo? – GameScripting

1

Questa soluzione è un po 'complicata ma funziona.

Dato questo controllo utente:

<Grid> 
    <StackPanel> 
     <WpfApplication1:FilePicker SelectedFilePath ="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> 
     <TextBlock Text="{Binding MyProperty}" /> 
    </StackPanel> 
</Grid> 

E il suo viewmodel:

public class MainWindowViewModel : INotifyPropertyChanged 
{ 
    #region Implementation of INotifyPropertyChanged 

    public event PropertyChangedEventHandler PropertyChanged; 

    public void OnPropertyChanged(string e) 
    { 
     var handler = PropertyChanged; 
     if (handler != null) handler(this, new PropertyChangedEventArgs(e)); 
    } 

    #endregion 

    private string _myProperty; 
    public string MyProperty 
    { 
     get { return _myProperty; } 
     set 
     { 
      _myProperty = value; 
      OnPropertyChanged("MyProperty"); 
     } 
    } 
} 

XAML per il controllo filepicker:

<Grid> 
    <TextBox x:Name="TextBox_FilePath" DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type WpfApplication1:FilePicker}}}" Text="{Binding SelectedFilePath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> 
</Grid> 

CodeBehind per il controllo filepicker:

public partial class FilePicker : UserControl 
{ 
    public FilePicker() 
    { 
     InitializeComponent(); 
    } 

    /* private PROXY DP*/ 
    private static readonly DependencyProperty TextProperty = 
     TextBox.TextProperty.AddOwner(typeof(FilePicker)); 

    /* public DP that will fire getter/setter for private DP */ 
    public static readonly DependencyProperty SelectedFilePathProperty = 
     DependencyProperty.Register("SelectedFilePath", typeof(string), typeof(FilePicker), new PropertyMetadata(default(string))); 

    public string SelectedFilePath 
    { 
     get { return (string)GetValue(TextProperty); } 
     set { SetValue(TextProperty, value); } 
    } 
} 

Funziona come un fascino.

+0

completo Gist può essere trovato qui: https://gist.github.com/2917066 –

+0

Grazie mille, senza il tuo esempio non vorrei farlo funzionare! – GameScripting

0

Come ho avuto problemi di comprensione H.B.s answer ho fatto un piccolo grafico che mi ha aiutato a capire cosa sta succedendo sotto il cofano. Ecco qui;

enter image description here

forse aiuta qualcun altro :)

+0

Ora capisco cosa non hai ottenuto: P –

Problemi correlati