WPF Material 设计 ComboBox 弹出窗口问题

WPF Material Design ComboBox Flyout issue

我在 WPF Framework 4.6.1 应用程序中使用 MaterialDesignThemes 2.6.0。

如果我单击 StackPanel 中的 ComboBox,第一次单击时弹出按钮不透明:

.

如果我单击 DataGrid 中的组合框,弹出窗口将显示为透明:

我必须再次点击才能正确显示:

App.xaml:

<Application x:Class="WpfApp1.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApp1"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Dark.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.Blue.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.DeepPurple.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

MainWindow.xaml:

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:vm="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Background="{DynamicResource MaterialDesignPaper}"
        TextElement.Foreground="{DynamicResource MaterialDesignBody}"
      Title="MainWindow" Height="250" Width="400">
    <Window.DataContext>
        <vm:ViewModel/>
    </Window.DataContext>
    <StackPanel>
        <ComboBox ItemsSource="{Binding ComboItems}"/>
        <DataGrid ItemsSource="{Binding ComboItems}"
                  AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTemplateColumn Header="Combo" Width="200">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},
                                                            Path = DataContext.ComboItems}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </StackPanel>
</Window>

ViewModel.cs:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp1
{
    public class ViewModel : INotifyPropertyChanged
    {
        private ObservableCollection<string> _comboItems;

        public ObservableCollection<string> ComboItems
        {
            get => _comboItems;
            set
            {
                if (value == _comboItems) return;
                _comboItems = value;
                OnPropertyChanged();
            }
        }

        public ViewModel()
        {
            _comboItems = new ObservableCollection<string>()
            {
                "Item 1",
                "Item 2"
            };
        }

        #region INotify support
        public event PropertyChangedEventHandler PropertyChanged;

        void OnPropertyChanged([CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        #endregion
    }
}

我想避免在第一次点击时出现透明弹出窗口。 任何帮助表示赞赏。

编辑:我在 github

上开了一个问题

我也有这个问题。我认为这是一个错误,因为在其他区域的背景下处理透明度。我为此找到了一个解决方案(实际上是 hack ;-P),并通过使组合框背景在下拉菜单打开时不透明并在关闭时恢复透明来制作一个实用程序 class。

更新:

添加了 100 毫秒的延迟,否则它无法正常工作。

using System;
using System.Windows.Controls;
using System.Windows.Media;
using System.Threading.Tasks;

namespace LogisticsNote.Utils
{
public class ManageCombo
{
    private static Brush OPAQUE_BACKGROUND_ON_OPEN = Brushes.WhiteSmoke;

    public static void SetBackgroundManagementEvents(params ComboBox[] combo)
    {
        foreach (ComboBox c in combo) SetBackgroundManagementEvents(c);
    }

    public static void SetBackgroundManagementEvents(ComboBox combo)
    {
        combo.DropDownOpened += Combo_DropDownOpened;
        combo.DropDownClosed += (s, e) =>
            (s as ComboBox).Background = Brushes.Transparent;
    }

    private static void Combo_DropDownOpened(object sender, EventArgs e)
    {
        var combo = sender as ComboBox;
        combo.IsDropDownOpen = false;
        if (combo.Items.Count == 0)
        {
            combo.Background = Brushes.Transparent;
            return;
        }

        combo.DropDownOpened -= Combo_DropDownOpened;
        combo.Background = OPAQUE_BACKGROUND_ON_OPEN;
        Task.Delay(100).ContinueWith(_ =>
        {
            combo.Dispatcher.Invoke((Action)(() =>
            {
                combo.IsDropDownOpen = true;
                combo.DropDownOpened += Combo_DropDownOpened;
            }));
        });
    }
}
}

我还做到了在没有项目时不打开下拉菜单。这是因为组合框在没有项目时会出现奇怪的行为。

您可以使用class喜欢

ManageCombo.SetBackgroundManagementEvents ( 
    combo1, combo2,      // Set to all combos in UI
    combo3, combo4
);

问题已通过发布 3.1.0 解决。