包含从WPF中的集合动态创建的复选框的菜单项

jdgnovmf  于 2022-11-18  发布在  其他
关注(0)|答案(1)|浏览(128)

我是WPF的新手,不幸的是,我只习惯于使用WinForms。我想征求一下绑定方面的建议。

我想填充语言的菜单项,如下图所示

我已经在我的viewModel中获得了以语言名称为键、以bool为值的字典:

internal Dictionary<string,bool> Languages { get; set; }

#endregion
public MainWindowViewModel()
{
    Loc = new Locale(CurrentLanguage);
    Languages = Loc.GetAvailableLanguages();
}

我已经通过将它们添加到MainWindowView.xaml文件后面的代码中来处理它:

public partial class MainWindow : Window
{

    MainWindowViewModel viewModel;
    public MainWindow()
    {
        viewModel = new MainWindowViewModel();
        DataContext = viewModel;
        InitializeComponent();
        PopulateMILanguages();
    }

private void PopulateMILanguages()
{
    foreach (var lng in viewModel.Languages)
    {
        MenuItem mi = new MenuItem();
        mi.IsCheckable = true;
        mi.Header = lng.Key;
        mi.Checked += Mi_Checked;
        MI_Lngs.Items.Add(mi);
        mi.IsChecked = lng.Value;
        if (lng.Key.ToLowerInvariant() == 
            Settings.Default.LastSelectedLanguage.ToLowerInvariant())
        {
            mi.IsChecked = true;
        }
    }
}

private void Mi_Checked(object sender, RoutedEventArgs e)
{
    MenuItem menuItem = sender as MenuItem;
    viewModel.CurrentLanguage = menuItem.Header.ToString()
        .ToLowerInvariant();
    Settings.Default.LastSelectedLanguage=viewModel.CurrentLanguage;
    foreach (MenuItem mi in MI_Lngs.Items)
    {
        if (mi.Header != menuItem.Header)
        {
            mi.IsChecked = false;
        }
    }
}

    private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
    {
        Settings.Default.Save();
    }
}

我真的不喜欢这个解决方案,但是我无法在xaml中处理它来填充集合:

<!--    LANGUAGE    -->
                <MenuItem x:Name="MI_Lngs" Header="{Binding Loc[Lng]}"
                          Style="{StaticResource MenuItemToolbar}">
                    <MenuItem.Icon>
                        <Image Source="/Assets/languages.png"/>
                    </MenuItem.Icon>
                    <MenuItem.ToolTip>
                        <ToolTip Content="{Binding Loc[Lng_TT]}"/>
                    </MenuItem.ToolTip>
                </MenuItem>

有人能给予我一个建议,如何处理它,以填补菜单项从集合,也能够捕捉检查的事件?
先谢了
伊日

sdnqo3pr

sdnqo3pr1#

您可以将此菜单与下面的视图模型一起使用,以获得所需的功能。

<Menu>
    <MenuItem Header="File"/>
    <MenuItem Header="Settings">
        <MenuItem Header="Application"/>
        <MenuItem Header="Language" ItemsSource="{Binding Languages}">
            <MenuItem.ItemContainerStyle>
                <Style>
                    <Setter Property="MenuItem.IsCheckable" Value="True"/>
                    <Setter Property="MenuItem.Header" Value="{Binding Header, Mode=OneWay}"/>
                    <Setter Property="MenuItem.IsChecked" Value="{Binding IsSelected, Mode=OneWay}"/>
                    <Setter Property="MenuItem.Command" Value="{Binding DataContext.SelectLanguageCommand, RelativeSource={RelativeSource AncestorType=MenuItem}}"/>
                    <Setter Property="MenuItem.CommandParameter" Value="{Binding}"/>
                </Style>
            </MenuItem.ItemContainerStyle>
        </MenuItem>
    </MenuItem>
</Menu>

我使用CommunityToolkit.Mvvm库给予你一些想法。你可以使用另一个库。

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;

namespace WpfApp1.ViewModel
{
    public class MainWindowViewModel : ObservableObject
    {
        private ObservableCollection<Language> _languages = new();
        public ObservableCollection<Language> Languages
        {
            get => _languages;
            set => SetProperty(ref _languages, value);
        }

        public IRelayCommand SelectLanguageCommand { get; }

        public MainWindowViewModel()
        {
            Languages.Add(new Language { Header = "CZ", IsSelected = false });
            Languages.Add(new Language { Header = "EN", IsSelected = true });

            SelectLanguageCommand = new RelayCommand<Language>(l =>
            {
                if (l != null)
                {
                    foreach (Language item in Languages)
                    {
                        item.IsSelected = false;
                    }

                    l.IsSelected = true;
                }
            });
        }
    }

    public class Language : ObservableObject
    {
        private string? _header;
        public string? Header
        {
            get => _header;
            set => SetProperty(ref _header, value);
        }

        private bool _isSelected;
        public bool IsSelected
        {
            get => _isSelected;
            set => SetProperty(ref _isSelected, value);
        }
    }
}

相关问题