Как создать выделенные элементы в контекстном меню в wpf? - PullRequest
0 голосов
/ 21 апреля 2020

В настоящее время я работаю над внешним интерфейсом для эмулятора в WPF, и у меня возникают проблемы с этой, казалось бы, базовой c функцией.

Я пытаюсь создать простой выбор элементов из контекста меню (в данном случае изображения). Картинка объясняет это немного лучше:

image

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

Я попробовал несколько разных подходов, но не смог найти правильного решение (в частности, как управлять isChecked для не нажатых элементов).

Мое контекстное меню (xaml) выглядит так:

<ContextMenu>
    <MenuItem Header="PCSX2 Version" ItemsSource="{Binding Versions}">
        <MenuItem.ItemContainerStyle>
            <Style TargetType="MenuItem">
                <Setter Property="StaysOpenOnClick" Value="True" />
                <Setter Property="BindingGroup" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type MenuItem}}}" />
                <EventSetter Event="Click" Handler="SetVersion" />
            </Style>
        </MenuItem.ItemContainerStyle>
    </MenuItem>
    <MenuItem Header="Config" ItemsSource="{Binding Configs}" />
    <MenuItem Header="Create Config" BindingGroup="{Binding}" Click="ShowConfigWizard"/>
</ContextMenu>

И моя модель показана ниже, не так много работает в коде позади (функция SetVersion) пока. Как вы можете видеть ниже, я попробовал решение, связывающее Tuple, но не смог заставить его работать (значение ischecked никогда не обновлялось, несмотря на то, что условие привязки больше не выполнялось).

Я также пытался решение, основанное на переключателях (опять не смог заставить его работать), и просто установил флажок в false для всех элементов из кода позади (не удалось выбрать элементы меню одного уровня из привязки).

public class GameModel : ICloneable
{
    public string Game { get; set; }
    public string Path { get; set; }
    public IEnumerable<string> Versions { get; set; }
    public IEnumerable<Tuple<string, bool>> VersionsAndStates => Versions.Select(version => new Tuple<string, bool>(version, Version == version));
    public string Version { get; set; }
    public IEnumerable<string> Configs { get; set; }
    public string Config { get; set; }
    public string CoverPath { get; set; }

    object ICloneable.Clone() => Clone();
    public GameModel Clone() => (GameModel) MemberwiseClone();
}

1 Ответ

0 голосов
/ 22 апреля 2020

Как обычно, я только что опубликовал вопрос о решении, а потом понял, что я был так близко, просто небольшая недосмотр с моей стороны о том, как работает ViewModel. Я приведу свое решение ниже на случай, если у кого-то еще есть подобная проблема. Основное изменение было в моей модели.

public class GameModel : ICloneable, INotifyPropertyChanged
{
    public string Game { get; set; }
    public string Path { get; set; }
    public IEnumerable<string> Versions { get; set; }
    public IEnumerable<Tuple<string, bool>> VersionsAndStates => Versions.Select(version => new Tuple<string, bool>(version, Version == version));
    private string version;
    public string Version 
    {
        get => version;
        set
        {
            version = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Version)));
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(VersionsAndStates)));
        }
    }
    public IEnumerable<string> Configs { get; set; }
    public string Config { get; set; }
    public string CoverPath { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    object ICloneable.Clone() => Clone();
    public GameModel Clone() => (GameModel) MemberwiseClone();
}

и моем xaml

    <ContextMenu>
        <MenuItem Header="PCSX2 Version" ItemsSource="{Binding VersionsAndStates}">
            <MenuItem.ItemContainerStyle>
                <Style TargetType="MenuItem">
                    <Setter Property="Header" Value="{Binding Item1}" />
                    <Setter Property="IsChecked" Value="{Binding Item2, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
                    <Setter Property="StaysOpenOnClick" Value="True" />
                    <Setter Property="BindingGroup" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type MenuItem}}}" />
                    <EventSetter Event="Click" Handler="SetVersion" />
                </Style>
            </MenuItem.ItemContainerStyle>
        </MenuItem>
        <MenuItem Header="Config" ItemsSource="{Binding Configs}" />
        <MenuItem Header="Create Config" BindingGroup="{Binding}" Click="ShowConfigWizard"/>
    </ContextMenu>

И затем установка версии для модели на выбранный заголовок в моем коде позади

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...