2012-10-23 70 views
7

在MainWindow中,commandbinding正常工作。 在UserControl1中它不起作用。請注意datacontext的設置是正確的,這是由作爲綁定結果的按鈕的內容證明的。如何在wpf中的用戶控件中使用命令綁定?

我不想將usercontrol中的命令綁定到mainwindow中的命令或任何其他此類欺騙。我只是試圖複製我在UserControl1中的MainWindow中做的事情。

主窗口XAML

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

主窗口代碼隱藏

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

用戶控件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> 

用戶控件代碼隱藏

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

您是否在輸出窗口檢查錯誤?有沒有? –

+0

@BigDaddy沒有錯誤。 – Sam

回答

11

這是最好的解決辦法:

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

其他的解決方案:

您忘記設置的DataContext的UserControl1

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

並在此之後,你必須在的UserControl1 DataContext的網格中刪除。

此:

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

必須改成這樣:在用戶控件

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

解決方案,而設置的DataContext:

您必須更改ButtonContent和ClickHereCommand到的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)); 

而且在UserControl1構造函數:

public UserControl1() 
    { 
     InitializeComponent(); 

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

謝謝你的回答,但我相信這是不正確的。正如我在我原來的問題中所述,「按照按鈕的內容證明數據環境設置正確」。我本意設置datacontext這種方式,因爲在我的應用程序UserControl將包含依賴項屬性,我特別不想設置DataContext = this。 – Sam

+0

根據您的迴應,我在網格中更改了DataContext,如下所示:DataContext =「{Binding RelativeSource = {RelativeSource Mode = FindAncestor,AncestorType = {x:Type UserControl}}}」並且它有效。非常奇怪的是,按鈕內容的綁定工作正常,但命令綁定沒有...... – Sam

+0

@Sam當我第一次使用您的代碼時,Button內容的綁定對我無效。當你將你的屬性更改爲DependencyProperty時,它會工作。在這種情況下,您可以使用綁定的'DataContext =「{Binding ElementName = root}」'。 – kmatyaszek

8

在這裏我又近兩年我張貼了這個之後。我忘了WPF的這個小功能,果然它又咬了我一口。

上面標記的答案部分正確,但包含其他令人分心和/或不正確的內容。爲了清楚起見,我將強調問題是什麼解決方案。我這樣做比我的好,因爲我確信我會在大約十六個月後回到這裏。

這是問題所在。不要這樣做。您的綁定都將繼續,除了你的路由命令的工作:

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

的解決方案是使用相對源設置數據上下文如下:

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

的唯一答案我問到的問題是上面的問題(事實上可能有其他答案,但是到目前爲止,在這個問題上還沒有討論過)。 具體來說: 在usercontrol中設置「DataContext = this」不是一個解決方案,它實際上會中斷用於控制用戶控件的控件的綁定。 另外,只有作爲綁定目標的屬性必須是依賴項屬性。這個建議是不正確的。

+0

事實證明,您的問題僅僅是對如何在UserControls內部綁定DataContext的錯誤概念,如果得到這個,您將始終記住。 /stackoverflow.com/a/19199045/711061它是啓發性 – sam

+0

@sam您提供的鏈接中的解決方案與此問題中提供的解決方案有何不同? – Sam

+0

Altought解決方案是相同的,您不知道爲什麼您擁有編寫這些代碼;結果你在這個問題中偶爾會偶爾遇到一些問題,我只是想幫助更多地瞭解這些代碼的含義。 – sam