2010-09-13 61 views
1

我有一個帶有幾個文本框控件的wpf窗口。我需要應用將適用於一個上下文菜單到每個控制的一種常用的風格,我也如下全局定義它,WPF CommandParameter在上下文菜單中設置時未更新

<ContextMenu x:Key="textBoxMenu"> 
     <Separator/> 
     <MenuItem Header="Affirm" 
        Command="{Binding Path=AffirmCommand}" 
        CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type TextBox},AncestorLevel=1}}"/>      
    </ContextMenu> 

    <Style TargetType="{x:Type TextBox}" x:Key="TextBoxAffirmMenuStyle"> 
     <Setter Property="ContextMenu" Value="{DynamicResource textBoxMenu}" /> 
    </Style> 

我已經使用了一個命令取決於上下文菜單的對象上執行相應的方法,在這種情況下是文本框。

爲了唯一標識這些控件,我使用唯一的字符串爲每個控件設置了「標籤」屬性,並從設置爲目標文本框控件本身的命令參數訪問此標籤。

private bool CanAffirmExecute(object param) 
     { 

      string columnName = (param as FrameworkElement).Tag as string; 

      if (this.CheckIsAffirmed(columnName)) 
       return true; 
      else 
       return false; 
     } 

private void AffirmExecute(object param) 
     { 

      string columnName = (param as FrameworkElement).Tag as string; 

      this.Affirm(columnName); 
     } 

這樣做的問題是,一旦命令參數被設置爲一個特定的控制, 它不會在隨後的上下文菜單操作改變時對上不同的控制點擊。 Command參數保持靜態並只獲取第一個控件中設置的標記值。

我怎樣才能得到這個工作,以便我可以訪問使用該命令的控件的每個標籤值?

謝謝。

回答

0

ContextMenu位於其自己的可視化樹的根部,所以使用RelativeSource.FindAncestor的任何綁定都不會超過ContextMenu。

解決方法是使用PlacementTarget屬性的兩階段綁定,如下所示, 並分析方法OnAffirmCommand(object obj)中的對象參數以控制您的行爲。在這種情況下,該對象是實際的文本框。

這裏是上下文菜單定義:

<Window.Resources> 
    <ContextMenu x:Key="textBoxMenu"> 
    <Separator/> 
    <MenuItem Header="Affirm" 
      Command="{Binding Path=AffirmCommand}" 
      CommandParameter="{Binding PlacementTarget.Tag, 
            RelativeSource={RelativeSource FindAncestor, 
            AncestorType={x:Type ContextMenu}}}"/> 
    </ContextMenu> 

    <Style TargetType="{x:Type TextBox}" x:Key="TextBoxAffirmMenuStyle"> 
     <Setter Property="ContextMenu" Value="{StaticResource textBoxMenu}" /> 
    </Style> 
</Window.Resources> 

下面是文本框:

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition/> 
     <RowDefinition/> 
     <RowDefinition/> 
    </Grid.RowDefinitions> 

    <TextBox Grid.Row="0" ContextMenu="{StaticResource textBoxMenu}" Tag="{Binding RelativeSource={RelativeSource Self}}" Text="text in box 1"/> 
    <TextBox Grid.Row="1" ContextMenu="{StaticResource textBoxMenu}" Tag="{Binding RelativeSource={RelativeSource Self}}" Text="text in box 2"/> 
    <TextBox Grid.Row="2" ContextMenu="{StaticResource textBoxMenu}" Tag="{Binding RelativeSource={RelativeSource Self}}" Text="text in box 3"/> 
</Grid> 

這裏是一個ViewModel命令代碼:

public class MainViewModel : ViewModelBase 
{ 
    public ICommand AffirmCommand { get; set; } 

    public MainViewModel() 
    { 
    AffirmCommand = new DelegateCommand<object>(OnAffirmCommand, CanAffirmCommand); 
    } 

    private void OnAffirmCommand(object obj) 
    { 
    } 

    private bool CanAffirmCommand(object obj) 
    { 
    return true; 
    } 
} 
+0

感謝贊博尼。我用稍微不同的方式實現了這一點。看起來命令參數只綁定一次。我所做的是將CommandTarget綁定到展示位置目標,並將CommandTarget綁定到CommandParameter。由於每次打開上下文菜單時都會更新CommandTarget,因此命令參數會返回目標控件。我認爲你所建議的是一些類似於這種方法的東西。 – Deshan 2010-09-16 05:22:56

+0

感謝您的評論,請將您的代碼/解決方案作爲未來其他人的答案。 – Zamboni 2010-09-16 16:47:03