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

在NinjaTrader WPF Grid中实现枚举值下拉列表以填充TextBox的方案问询

在NinjaTrader WPF Grid中实现枚举值下拉列表以填充TextBox的方案问询

嘿,看起来你已经在NinjaTrader的WPF Grid里搭好了基础界面,现在就差给那个TextBox加上枚举值的下拉选择功能对吧?我给你两个实用的方案,全用C#实现,完全不用XAML或者网页相关的东西,贴合你的需求:

方案1:替换TextBox为ComboBox(最省心的原生方案)

WPF的ComboBox控件本身就支持下拉选择,完美匹配你的枚举值选择需求,而且实现起来非常简单,还能直接利用你枚举里的Display属性显示友好名称:

首先,记得先引用System.ComponentModel命名空间(因为要读取DisplayAttribute)。然后把你原来创建systemsLabelVal(TextBox)的代码替换成下面的ComboBox代码:

// 声明类成员变量
private ComboBox systemsComboBox;
private MySystems systemsValue = MySystems.NotSet; // 假设你的变量初始值是NotSet

// 替换原来的TextBox创建逻辑
this.systemsComboBox = new ComboBox
{
    Height = 20.0,
    Width = 60.0,
    FontSize = 10.0,
    HorizontalAlignment = HorizontalAlignment.Right,
    VerticalAlignment = VerticalAlignment.Center,
    SelectedValuePath = "Value", // 指定选中值对应枚举本身
    DisplayMemberPath = "Key"    // 指定显示的是友好名称
};

// 保持和原TextBox一致的样式
this.systemsComboBox.Foreground = Brushes.White;
this.systemsComboBox.Background = Brushes.Transparent;
this.systemsComboBox.BorderBrush = Brushes.Transparent;

// 填充枚举值,同时读取Display属性的友好名称
var enumOptions = Enum.GetValues(typeof(MySystems))
    .Cast<MySystems>()
    .Select(enumVal => new KeyValuePair<string, MySystems>(
        // 优先取Display的Name,没有的话用枚举本身的名称
        enumVal.GetType().GetMember(enumVal.ToString())[0].GetCustomAttribute<DisplayAttribute>()?.Name ?? enumVal.ToString(),
        enumVal
    ))
    .ToList();

this.systemsComboBox.ItemsSource = enumOptions;
// 设置默认选中项
this.systemsComboBox.SelectedValue = this.systemsValue;

// 绑定选择变更事件,更新你的变量和按钮内容
this.systemsComboBox.SelectionChanged += (sender, e) =>
{
    if (this.systemsComboBox.SelectedValue is MySystems selectedSystem)
    {
        this.systemsValue = selectedSystem;
        // 同步更新按钮的显示内容
        var selectedOption = enumOptions.First(opt => opt.Value == selectedSystem);
        this.Systemsbtn.Content = selectedOption.Key;
        this.Systemsbtn.Name = selectedOption.Key;
    }
};

// 添加到Grid中
Grid.SetColumnSpan(this.systemsComboBox, 3);
Grid.SetRow(this.systemsComboBox, 3);
grid5.Children.Add(this.systemsComboBox);

这个方案的好处是完全利用WPF原生控件,不用自己处理弹窗的显示隐藏,稳定性和维护性都更好,而且用户体验也符合标准的下拉选择习惯。

方案2:给TextBox添加Popup下拉列表(坚持用TextBox的场景)

如果你一定要保留TextBox,只在选中时弹出下拉列表,那可以用WPF的Popup控件配合ListBox来实现:

同样先引用System.ComponentModel,然后修改你的代码如下:

// 声明类成员变量
private TextBox systemsLabelVal;
private Popup systemsPopup;
private ListBox systemsListBox;
private MySystems systemsValue = MySystems.NotSet;

// 原来的TextBox创建逻辑,加上焦点事件
this.systemsLabelVal = new TextBox
{
    Text = GetEnumDisplayName(this.systemsValue),
    Height = 20.0,
    Width = 60.0,
    FontSize = 10.0,
    HorizontalAlignment = HorizontalAlignment.Right,
    VerticalAlignment = VerticalAlignment.Center,
    Foreground = Brushes.White,
    Background = Brushes.Transparent,
    BorderBrush = Brushes.Transparent,
    TextAlignment = TextAlignment.Center
};
this.systemsLabelVal.GotFocus += SystemsLabelVal_GotFocus;
this.systemsLabelVal.PreviewKeyDown += this.TextBox_PreviewKeyDown;
grid5.Children.Add(this.systemsLabelVal);

// 初始化Popup和ListBox
this.systemsPopup = new Popup
{
    PlacementTarget = this.systemsLabelVal,
    Placement = PlacementMode.Bottom, // 弹窗显示在TextBox下方
    AllowsTransparency = true,
    PopupAnimation = PopupAnimation.Fade
};

this.systemsListBox = new ListBox
{
    Width = this.systemsLabelVal.Width,
    Background = Brushes.Gray,
    Foreground = Brushes.White,
    BorderBrush = Brushes.DimGray
};

// 填充枚举值
var enumItems = Enum.GetValues(typeof(MySystems))
    .Cast<MySystems>()
    .Select(val => new
    {
        DisplayName = GetEnumDisplayName(val),
        Value = val
    })
    .ToList();
this.systemsListBox.ItemsSource = enumItems;
this.systemsListBox.DisplayMemberPath = "DisplayName";

// 绑定ListBox的选择事件
this.systemsListBox.SelectionChanged += SystemsListBox_SelectionChanged;
// 处理鼠标点击,避免弹窗提前关闭
this.systemsListBox.MouseUp += (s, args) =>
{
    if (this.systemsListBox.SelectedItem != null)
    {
        this.systemsPopup.IsOpen = false;
    }
};

this.systemsPopup.Child = this.systemsListBox;

// 辅助方法:获取枚举的Display名称
private string GetEnumDisplayName(MySystems enumVal)
{
    return enumVal.GetType().GetMember(enumVal.ToString())[0].GetCustomAttribute<DisplayAttribute>()?.Name ?? enumVal.ToString();
}

// 事件处理方法
private void SystemsLabelVal_GotFocus(object sender, RoutedEventArgs e)
{
    this.systemsPopup.IsOpen = true;
    // 让ListBox获得焦点,避免TextBox失去焦点后弹窗直接关闭
    this.systemsListBox.Focus();
}

private void SystemsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (this.systemsListBox.SelectedItem is dynamic selectedItem)
    {
        this.systemsValue = selectedItem.Value;
        this.systemsLabelVal.Text = selectedItem.DisplayName;
        // 同步更新按钮内容
        this.Systemsbtn.Content = selectedItem.DisplayName;
        this.Systemsbtn.Name = selectedItem.DisplayName;
    }
}

这个方案保留了TextBox的外观,只有在获取焦点时才弹出下拉列表,适合你想要保持原有界面样式的需求。

小提示

不管用哪个方案,都要确保你的枚举所在的命名空间被正确引用(using Profit_Bot_Enums;),另外如果你的systemsValue变量初始值不是NotSet,记得同步设置控件的默认选中项。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 08:20:32