2012-10-23 8 views
7

In MainWindow la bind del comando funziona correttamente. In UserControl1 non funziona. Nota che il datacontext è impostato correttamente come evidenziato dal contenuto del pulsante che è il risultato di un binding.Come utilizzare i collegamenti dei comandi nei controlli utente in wpf?

Non sto cercando di associare il comando in usercontrol a un comando in mainwindow o altri trucchi del genere. Sto solo cercando di replicare ciò che ho fatto in MainWindow in UserControl1.

MainWindow XAML

<StackPanel> 
    <Button Content="Click Here" Command="{Binding ClickHereCommand}" Height="25" Width="90"></Button> 
    <local:UserControl1></local:UserControl1> 
</StackPanel> 

Codice MainWindow Dietro

public partial class MainWindow : Window 
{ 
    public static RoutedCommand ClickHereCommand { get; set; } 

    public MainWindow() 
    { 
     InitializeComponent(); 
     this.DataContext = this; 
     ClickHereCommand = new RoutedCommand(); 
     CommandBindings.Add(new CommandBinding(ClickHereCommand, ClickHereExecuted)); 
    } 

    public void ClickHereExecuted(object sender, ExecutedRoutedEventArgs e) 
    { 
     System.Windows.MessageBox.Show("hello"); 
    } 
} 

UserControl XAML

<UserControl x:Class="CommandBindingTest.UserControl1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     mc:Ignorable="d" 
     d:DesignHeight="300" d:DesignWidth="300" x:Name="root"> 

<Grid DataContext="{Binding ElementName=root}" > 
    <Button Content="{Binding ButtonContent}" Command="{Binding ClickHereCommand}" Height="25" Width="90"></Button> 
</Grid> 
</UserControl> 

codice UserControl Dietro

public partial class UserControl1 : UserControl, INotifyPropertyChanged 
{ 
    private string _ButtonContent; 
    public string ButtonContent 
    { 
     get { return _ButtonContent; } 
     set 
     { 
      if (_ButtonContent != value) 
      { 
       _ButtonContent = value; 
       OnPropertyChanged("ButtonContent"); 
      } 
     } 
    } 

    public static RoutedCommand ClickHereCommand { get; set; } 


    public UserControl1() 
    { 
     InitializeComponent(); 
     ClickHereCommand = new RoutedCommand(); 
     CommandBindings.Add(new CommandBinding(ClickHereCommand, ClickHereExecuted)); 
     ButtonContent = "Click Here"; 
    } 

    public void ClickHereExecuted(object sender, ExecutedRoutedEventArgs e) 
    { 
     System.Windows.MessageBox.Show("hello from UserControl1"); 
    } 


    #region INotifyPropertyChanged Members 
    public event PropertyChangedEventHandler PropertyChanged; 

    public void OnPropertyChanged(string name) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(name)); 
     } 
    } 
    #endregion 
} 
+0

Stai controllando la finestra di output per errori? Ci sono? –

+0

@BigDaddy Nessun errore. – Sam

risposta

11

E 'la soluzione migliore:

<Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}" > 
     <Button Content="{Binding ButtonContent}" Command="{Binding ClickHereCommand}" Height="25" Width="90"></Button> 
</Grid> 

Altre soluzioni:

hai dimenticato di impostare DataContext-UserControl1.

public UserControl1() 
     { 
      InitializeComponent(); 
      ClickHereCommand = new RoutedCommand(); 
      CommandBindings.Add(new CommandBinding(ClickHereCommand, ClickHereExecuted)); 
      ButtonContent = "Click Here"; 
      this.DataContext = this; 
     } 

E dopo questo è necessario eliminare in UserControl1 DataContext in griglia.

questo:

<Grid DataContext="{Binding ElementName=root}" > 
    <Button Content="{Binding ButtonContent}" Command="{Binding ClickHereCommand}" Height="25" Width="90"></Button> 
</Grid> 

è necessario modificare a questo:

<Grid> 
     <Button Content="{Binding ButtonContent}" Command="{Binding ClickHereCommand}" Height="25" Width="90"></Button> 
</Grid> 

soluzione senza impostare DataContext in UserControl:

È necessario modificare ButtonContent e ClickHereCommand a DependencyProperty.

 public string ButtonContent 
     { 
      get { return (string)GetValue(ButtonContentProperty); } 
      set { SetValue(ButtonContentProperty, value); } 
     } 

     public static readonly DependencyProperty ButtonContentProperty = 
      DependencyProperty.Register("ButtonContent", typeof(string), typeof(UserControl1), new UIPropertyMetadata(string.Empty)); 

     public RoutedCommand ClickHereCommand 
     { 
      get { return (RoutedCommand)GetValue(ClickHereCommandProperty); } 
      set { SetValue(ClickHereCommandProperty, value); } 
     } 

     public static readonly DependencyProperty ClickHereCommandProperty = 
      DependencyProperty.Register("ClickHereCommand", typeof(RoutedCommand), typeof(UserControl1), new UIPropertyMetadata(null)); 

E in ctor di UserControl1:

public UserControl1() 
    { 
     InitializeComponent(); 

     ClickHereCommand = new RoutedCommand(); 
     CommandBindings.Add(new CommandBinding(ClickHereCommand, ClickHereExecuted));    
     ButtonContent = "Click Here"; 
     //this.DataContext = this; 
    } 
+0

grazie per la risposta, ma credo che non sia corretto. Come ho affermato nella mia domanda iniziale, "datacontext è impostato correttamente come è evidenziato dal contenuto del pulsante". In questo modo ho impostato il datacontext in modo imprevisto perché nella mia app UserControl conterrà le proprietà di dipendenza e in particolare non desidero impostare DataContext = this. – Sam

+0

In base alla risposta, ho modificato DataContext nella griglia come segue: DataContext = "{Binding RelativeSource = {RelativeSource Mode = FindAncestor, AncestorType = {x: Type UserControl}}}" e funziona. È molto strano che il binding per il contenuto del pulsante abbia funzionato bene, ma il binding del comando non lo ha fatto ... – Sam

+0

@Sam quando ho usato il tuo codice la prima volta che il binding per il contenuto del pulsante non ha funzionato per me. Funzionerà quando cambierai le proprietà in DependencyProperty. In questo caso puoi usare il tuo binding 'DataContext =" {Binding ElementName = root} "'. – kmatyaszek

8

Eccomi di nuovo quasi due anni dopo che ho postato questo. Ho dimenticato questa piccola funzionalità di WPF e sicuramente mi ha morso di nuovo.

La risposta sopra indicata è parzialmente corretta ma contiene altro contenuto che distrae e/o non è corretto. Per chiarezza evidenzierò qual è il problema è quale sia la soluzione. Lo sto facendo di più a mio vantaggio, perché sono sicuro che tornerò qui tra circa sedici mesi.

Ecco il problema. Non farlo.I suoi attacchi saranno tutti continuano a lavorare tranne che per i comandi indirizzati:

<UserControl x:Class="CommandBindingTest.UserControl1" 
    // snip 
    d:DesignHeight="300" d:DesignWidth="300" x:Name="root"> 

    <Grid DataContext="{Binding ElementName=root}" > 
     <Button Content="{Binding ButtonContent}" Command="{Binding ClickHereCommand}" Height="25" Width="90"> 
     </Button> 
    </Grid> 

La soluzione è utilizzare fonte relativa alla creazione del contesto dati come segue:

<Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}" > 
    <Button Content="{Binding ButtonContent}" Command="{Binding ClickHereCommand}" Height="25" Width="90"> 
    </Button> 
</Grid> 

L'unica risposta alla il problema che ho posto è quello sopra (potrebbero infatti esserci altre risposte ma non sono state discusse finora in questa domanda). In particolare: L'impostazione "DataContext = this" nell'usercontrol NON è una soluzione e in pratica interromperà i binding nel controllo che ospita il controllo utente. Inoltre, solo le proprietà che sono le destinazioni dei binding devono essere proprietà di dipendenza. Questo suggerimento non è corretto.

+0

Il tuo problema è semplicemente un equivoco su come associare DataContext all'interno di UserControls. Se ottieni questo, ricorderai sempre. /stackoverflow.com/a/19199045/711061 è illuminante – sam

+0

@sam Come è la soluzione nel link che hai fornito diverso dalla soluzione fornita in questa domanda? – Sam

+0

Altought la soluzione è la stessa, non sai perché hai scrivere quel codice, di conseguenza inciampi di tanto in tanto in questo problema, volevo solo aiutare a dare un po 'di più al significato di questo codice. – sam

Problemi correlati