You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinUI 3中如何将DropDownButton的项绑定到ViewModel?

WinUI3 DropDownButton 绑定 ViewModel 集合的实现方法

由于MenuFlyout本身没有ItemsSource属性,无法直接绑定集合,你可以通过以下两种常用方式实现数据绑定:

方法一:使用 ItemsRepeater 自定义 Flyout 内容

这种方式灵活性高,可完全自定义下拉项样式,且符合MVVM规范:

1. 定义 ViewModel 中的语言数据结构与集合

public class LanguageItem
{
    public string DisplayName { get; set; }
    public string CultureTag { get; set; }
}

public class MainViewModel : ObservableObject
{
    // 选中的语言,用于同步按钮显示文本
    private LanguageItem _selectedLanguage;
    public LanguageItem SelectedLanguage
    {
        get => _selectedLanguage;
        set => SetProperty(ref _selectedLanguage, value);
    }

    // 语言集合
    public ObservableCollection<LanguageItem> Languages { get; } = new()
    {
        new LanguageItem { DisplayName = "English", CultureTag = "en-EN" },
        new LanguageItem { DisplayName = "中文", CultureTag = "zh-CN" },
        new LanguageItem { DisplayName = "日本語", CultureTag = "ja-JP" }
    };

    // 选中命令
    private ICommand _languageSelectedCommand;
    public ICommand LanguageSelectedCommand => _languageSelectedCommand ??= new RelayCommand<LanguageItem>(item =>
    {
        SelectedLanguage = item;
        // 这里添加语言切换等业务逻辑
    });
}

2. XAML 绑定实现

将MenuFlyout替换为普通Flyout,内部用ItemsRepeater渲染集合:

<!-- 假设页面根布局命名为RootGrid -->
<Grid x:Name="RootGrid" DataContext="{StaticResource MainViewModel}">
    <DropDownButton Width="100" Grid.Column="2" ToolTipService.ToolTip="Language">
        <TextBlock FontSize="14" Text="{Binding SelectedLanguage.DisplayName, FallbackValue='Select language'}"/>
        <DropDownButton.Flyout>
            <Flyout Placement="BottomEdgeAlignedLeft">
                <ItemsRepeater ItemsSource="{Binding Languages}">
                    <ItemsRepeater.ItemTemplate>
                        <DataTemplate x:DataType="local:LanguageItem">
                            <Button 
                                Style="{StaticResource TextBlockButtonStyle}"
                                Command="{Binding DataContext.LanguageSelectedCommand, ElementName=RootGrid}"
                                CommandParameter="{Binding}">
                                <TextBlock Text="{Binding DisplayName}"/>
                            </Button>
                        </DataTemplate>
                    </ItemsRepeater.ItemTemplate>
                    <ItemsRepeater.Layout>
                        <StackLayout Spacing="0"/>
                    </ItemsRepeater.Layout>
                </ItemsRepeater>
            </Flyout>
        </DropDownButton.Flyout>
    </DropDownButton>
</Grid>

方法二:通过代码生成 MenuFlyoutItem 并绑定

如果想保留MenuFlyout的原生样式,可在ViewModel中维护MenuFlyoutItem集合,再通过后台代码绑定到Flyout:

1. ViewModel 中定义菜单项集合

public class MainViewModel
{
    public ObservableCollection<MenuFlyoutItem> LanguageMenuItems { get; } = new();

    public MainViewModel()
    {
        LanguageMenuItems.Add(new MenuFlyoutItem { Text = "English", Tag = "en-EN" });
        LanguageMenuItems.Add(new MenuFlyoutItem { Text = "中文", Tag = "zh-CN" });
        LanguageMenuItems.Add(new MenuFlyoutItem { Text = "日本語", Tag = "ja-JP" });

        // 绑定点击事件
        foreach (var item in LanguageMenuItems)
        {
            item.Click += OnLanguageItemClicked;
        }
    }

    private void OnLanguageItemClicked(object sender, RoutedEventArgs e)
    {
        if (sender is MenuFlyoutItem item)
        {
            // 处理选中逻辑
        }
    }
}

2. XAML 与后台代码绑定

<DropDownButton x:Name="LanguageDropdown" Width="100" Grid.Column="2" ToolTipService.ToolTip="Language">
    <TextBlock FontSize="14" Text="Select language"/>
    <DropDownButton.Flyout>
        <MenuFlyout x:Name="LanguageMenu" Placement="BottomEdgeAlignedLeft"/>
    </DropDownButton.Flyout>
</DropDownButton>

后台代码在页面加载时赋值:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
    if (DataContext is MainViewModel vm)
    {
        foreach (var item in vm.LanguageMenuItems)
        {
            LanguageMenu.Items.Add(item);
        }
    }
}

补充说明

  • 优先推荐方法一,避免后台事件绑定,更贴合MVVM模式;若需要原生菜单样式,可选择方法二。
  • 确保页面的DataContext已正确设置为对应的ViewModel,比如在页面构造函数中赋值或通过资源声明。

内容的提问来源于stack exchange,提问作者holycreeper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 18:22:49