2010-06-24 56 views
5

我正在嘗試設置MenuItem,這將有一個可以選擇的頁碼子菜單。我想將ItemsSource綁定到頁碼列表(實際上是通過創建列表的轉換器將其綁定到PageCount),然後將子菜單中每個MenuItemIsChecked屬性綁定到PageIndex。我的問題是第二個綁定,因爲它也需要一個轉換器,但該轉換器需要知道MenuItem代表的頁碼,但我不知道如何將該信息傳遞給轉換器。這是迄今爲止我嘗試過的。綁定ItemsSource和IsChecked的MenuItem以獲取WPF中的可選項目列表

<MenuItem Header="_Goto Page" 
      ItemsSource="{Binding 
         Path=CurrentImage.PageCount, 
         Converter={StaticResource countToList}}"> 
    <MenuItem.ItemContainerStyle> 
     <Style TargetType="MenuItem"> 
      <Setter Property="IsCheckable" 
        Value="True"/> 
      <Setter Property="IsChecked" 
        Value="{Binding 
          ElementName=MainWindow, 
          Path=CurrentImage.PageIndex, 
          Mode=TwoWay, 
          Converter={StaticResource pageNumChecked}, 
          ConverterParameter={Binding 
               RelativeSource={RelativeSource Self}, 
               Path=Content}}"/> 
     </Style> 
    </MenuItem.ItemContainerStyle> 
</MenuItem> 

當然,問題是,ConverterParameter不能被綁定,因爲它不是一個DependencyProperty。所以我的問題是如何傳遞我需要的信息,或者有另一種方式來實現這一點。

注意:我已經試過把MenuItem放在ListBox的內部,就綁定而言效果很好,但是導致子菜單以非標準方式運行。那就是當你打開子菜單時,整個ListBox被當作一個MenuItem

編輯

所以這裏就是我已經得到了工作至今。我嘗試綁定到隱藏的ListBox,但是當我將MenuItem.ItemsSource綁定到'ListBox.Items'時,我得到了int s的列表,而不是我需要獲得IsSelected屬性的列表ListBoxItem。所以我最終使用Quartermeister的建議,使用MultiBinding來獲取IsChecked屬性以模式綁定到PageIndex。爲了處理另一個方向,我在Click事件中使用了一個事件處理程序。值得注意的是,起初我已將IsCheckable設置爲true,並且正在與Checked事件一起工作,但這導致了一些奇怪的行爲。

<MenuItem x:Name="GotoPageMenuItem" Header="_Goto Page" 
      ItemsSource="{Binding Path=CurrentImage.PageCount, 
           Converter={StaticResource countToList}}"> 
    <MenuItem.ItemContainerStyle> 
     <Style TargetType="MenuItem"> 
      <Setter Property="IsCheckable" 
        Value="False"/> 
      <EventSetter Event="Click" 
         Handler="GotoPageMenuItem_Click"/> 
      <Setter Property="IsChecked"> 
       <Setter.Value> 
        <MultiBinding Converter="{StaticResource pageNumChecked}" 
               Mode="OneWay"> 
         <Binding RelativeSource="{RelativeSource FindAncestor, 
                AncestorType={x:Type Window}}" 
                Path="CurrentImage.PageIndex" 
                Mode="OneWay"/> 
         <Binding RelativeSource="{RelativeSource Self}" 
                Path="Header" 
                Mode="OneWay"/> 
        </MultiBinding> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </MenuItem.ItemContainerStyle> 
</MenuItem> 

而這裏的GotoPageMenuItem_Click代碼

private void GotoPageMenuItem_Click(object sender, RoutedEventArgs e) 
{ 
    var item = sender as MenuItem; 
    if (item != null) 
    { 
     //If the item is already checked then we don't need to do anything 
     if (!item.IsChecked) 
     { 
      var pageNum = (int)item.Header; 
      CurrentImage.PageIndex = (pageNum - 1); 
     } 
    } 
} 

回答

3

你想使用MultiBinding你可以做什麼?

<Setter Property="IsChecked"> 
    <Setter.Value> 
     <MultiBinding Converter="{StaticResource pageNumChecked}"> 
      <Binding ElementName="MainWindow" Path="CurrentImage.PageIndex" Mode="TwoWay"/> 
      <Binding RelativeSource="{RelativeSource Self}" Path="Content"/> 
     </MultiBinding> 
    </Setter.Value> 
</Setter> 

有你pageNumChecked轉換器實現IMultiValueConverter代替的IValueConverter和轉換將得到每個孩子結合的結果的數組。在這種情況下,它將是一個兩元素數組,其中第一個元素是當前輸入,PageIndex,第二個索引是您當前的ConverterParameter,Content。如果你想要雙向綁定,ConvertBack將需要返回一個雙元素數組,並且你會返回Binding.DoNothing作爲第二個參數,這樣它就不會嘗試更新內容。

+0

這並不適用於兩項工作因爲我需要知道兩個方向的Content值,並且只傳遞給Convert而不是ConvertBack。 – juharr 2010-06-25 13:03:29

+0

即使這個想法在兩個方向都不起作用,它讓我在那裏一半,所以,你贏了。 – juharr 2010-06-25 21:27:22

3

聽起來就像你正試圖建立動態菜單,控制每個菜單項的選中狀態。
我擴展了一些我編寫的代碼,用MVVM模式在WPF中構建動態菜單並添加了檢查邏輯。

這裏是XAML:

<Menu DockPanel.Dock="Top"> 
    <MenuItem ItemsSource="{Binding Commands}" 
       Header="_Item Container Style"> 
     <MenuItem.ItemContainerStyle> 
      <Style TargetType="{x:Type MenuItem}"> 
       <Setter Property="IsCheckable" Value="True"/> 
       <Setter Property="IsChecked" Value="{Binding Path=Checked}"/> 
       <Setter Property="Header" Value="{Binding Path=Text}" /> 
       <Setter Property="Command" Value="{Binding Path=Command}" /> 
       <Setter Property="CommandParameter" Value="{Binding Path=Parameter}" /> 
      </Style> 
     </MenuItem.ItemContainerStyle> 
    </MenuItem> 
</Menu> 

這裏是視圖模型:

public class MainViewModel : ViewModelBase 
{ 
    public MainViewModel() 
    { 
    GoCommand = new DelegateCommand<object>(OnGoCommand, CanGoCommand); 
    LoadCommands(); 
    } 

    private List<MyCommand> _commands = new List<MyCommand>(); 
    public List<MyCommand> Commands 
    { 
    get { return _commands; } 
    } 

    private void LoadCommands() 
    { 
    MyCommand c1 = new MyCommand { Command = GoCommand, Parameter = "1", Text = "Menu1", Checked = true}; 
    MyCommand c2 = new MyCommand { Command = GoCommand, Parameter = "2", Text = "Menu2", Checked = true }; 
    MyCommand c3 = new MyCommand { Command = GoCommand, Parameter = "3", Text = "Menu3", Checked = false }; 
    MyCommand c4 = new MyCommand { Command = GoCommand, Parameter = "4", Text = "Menu4", Checked = true }; 
    MyCommand c5 = new MyCommand { Command = GoCommand, Parameter = "5", Text = "Menu5", Checked = false }; 
    _commands.Add(c1); 
    _commands.Add(c2); 
    _commands.Add(c3); 
    _commands.Add(c4); 
    _commands.Add(c5); 
    } 

    public ICommand GoCommand { get; private set; } 
    private void OnGoCommand(object obj) 
    { 
    } 

    private bool CanGoCommand(object obj) 
    { 
    return true; 
    } 
} 

這裏是保存命令類:

public class MyCommand 
    { 
    public ICommand Command { get; set; } 
    public string Text { get; set; } 
    public string Parameter { get; set; } 
    public Boolean Checked { get; set; } 
    } 
+0

這個例子的問題是菜單項的數量是靜態的。在我的應用程序中,「CurrentImage」可以更改,然後我需要更新要匹配的菜單項的數量。此外,這看起來就像代碼中的事件處理創建菜單項,然後處理每個菜單項「Checked」事件,我希望有一個XAML解決方案。 – juharr 2010-06-25 16:13:01

+0

您可以擴展我的解決方案以在CurrentImage更改時重新加載命令列表,但我同意這是很多(簡單)代碼。如果您發佈CurrentImage的代碼,可能會幫助我和其他人更好地瞭解您的問題。 – Zamboni 2010-06-25 16:37:11

相關問題