Привязка ItemsSource и IsChecked MenuItem для получения списка поддающихся проверке объектов в WPF

Я пытаюсь установить a MenuItem это будет иметь подменю номеров страниц, которые могут быть выбраны. Я хочу связать ItemsSource к списку номеров страниц (на самом деле к PageCount с преобразователем, создающим список) и затем, связывают IsChecked свойство каждого MenuItem в подменю к PageIndex. Моя проблема со второй привязкой, поскольку она также требует преобразователя, но тот преобразователь должен знать номер страницы что MenuItem представляет, но я не могу выяснить, как передать ту информацию преобразователю. Вот то, что я попробовал до сих пор.

<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 не может быть связан, поскольку это не a DependencyProperty. Таким образом, мой вопрос состоит в том, как я могу передать в информации, в которой я нуждаюсь или есть ли другой способ сделать это.

Примечание: Я уже попытался поместить MenuItems в a ListBox который работавший действительно хорошо насколько привязка затронута, но заставила подменю вести себя нестандартным способом. Это - при открытии подменю все ListBox рассматривался как один MenuItem.

Править

Таким образом, вот то, что я взялся за работу до сих пор. Я пытался связать со скрытым ListBox но когда я связал MenuItem.ItemsSource к 'ListBox. Объекты я получил список ints вместо списка ListBoxItems, который я должен был получить IsSelected свойство. Таким образом, я закончил тем, что использовал предложение Quartermeister использования MultiBinding для получения IsChecked свойство для привязки с PageIndex в OneWay режим. Для обработки другого направления, я использовал обработчик событий на 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);
        }
    }
}
5
задан juharr 25 June 2010 в 21:22
поделиться

2 ответа

Можете ли вы сделать то, что хотите, используя 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, и Convert получит массив с результатом каждого дочернего связывания. В данном случае это будет двухэлементный массив, где первым элементом будет ваш текущий вход, PageIndex, а вторым индексом - текущий параметр конвертера, Content. Если вы хотите двустороннее связывание, ConvertBack должен вернуть двухэлементный массив, а для второго параметра вы вернете Binding.DoNothing, чтобы он не пытался обновить Content.

3
ответ дан 14 December 2019 в 13:26
поделиться

Похоже, вы пытаетесь создать динамическое меню, которое контролирует отмеченное состояние каждого пункта меню.
Я расширил написанный мной код для создания динамических меню в WPF с шаблоном MVVM и добавил проверенную логику.

Вот 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; }
  }
3
ответ дан 14 December 2019 в 13:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: