Files
MRCC/launcher/PCL-CE/Plain Craft Launcher 2/Controls/MyComboBox.cs
T
xyou f70b061d1a
CI / Go Backend (push) Canceled after 0s
feat: 项目初始化 + 3D方块世界原型 + AI助搭系统
初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器

HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块

Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚

AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
2026-08-08 14:07:56 +08:00

243 lines
7.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using PCL.Core.App.Localization;
namespace PCL;
public class MyComboBox : ComboBox
{
public delegate void TextChangedEventHandler(object sender, TextChangedEventArgs e);
public static readonly DependencyProperty HintTextProperty = DependencyProperty.Register("HintText", typeof(string),
typeof(MyComboBox), new PropertyMetadata("", (d, e) =>
{
var c = (MyComboBox)d;
if (c.textBox is not null)
c.textBox.HintText = (string)e.NewValue;
}));
private string _Text;
// 鼠标按下接口
private bool isMouseDown;
// 修复 WPF Bug:下拉框文本修改后,依然误认为还选择着此前的选项,导致再次点击该选项时内容不变
private bool isTextChanging;
private double realWidth; // 由于下拉框 Popup 宽度与 Width 一致,故不能为 NaNAuto
private MyTextBox textBox;
// 基础
public int Uuid = ModBase.GetUuid();
public MyComboBox()
{
_Text = SelectedItem?.ToString() ?? "";
PreviewMouseLeftButtonDown += MyComboBox_PreviewMouseLeftButtonDown;
PreviewMouseLeftButtonUp += MyComboBox_PreviewMouseLeftButtonUp;
MouseLeave += MyComboBox_PreviewMouseLeftButtonUp;
IsEnabledChanged += (_, _) => RefreshColor();
MouseEnter += (_, _) => RefreshColor();
MouseLeave += (_, _) => RefreshColor();
PreviewMouseLeftButtonDown += (_, _) => RefreshColor();
PreviewMouseLeftButtonUp += (_, _) => RefreshColor();
GotKeyboardFocus += (_, _) => RefreshColor();
DropDownOpened += MyComboBox_DropDownOpened;
DropDownClosed += MyComboBox_DropDownClosed;
TextChanged += MyComboBox_TextChanged;
}
public string HintText
{
get => (string)GetValue(HintTextProperty);
set => SetValue(HintTextProperty, value);
}
public new string Text
{
get
{
if (IsEditable)
{
if (textBox is null) return _Text ?? "";
return textBox.Text ?? "";
}
return (SelectedItem ?? "").ToString();
}
set
{
if (IsEditable)
{
if (textBox is null)
_Text = value;
else
textBox.Text = value;
}
else
{
throw new NotSupportedException("该 ComboBox 不支持修改文本。");
}
}
}
public bool DropDownWidthSync { get; set; } = true;
public ContentPresenter ContentPresenter => (ContentPresenter)Template.FindName("PART_Content", this);
public event TextChangedEventHandler? TextChanged;
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (!IsEditable)
return;
try
{
textBox = (MyTextBox)Template.FindName("PART_EditableTextBox", this);
textBox.AddHandler(LostFocusEvent, new RoutedEventHandler((_, _) => RefreshColor()));
textBox.changedEventList.Add((sender, e) => TextChanged?.Invoke(sender, (TextChangedEventArgs)e));
textBox.Tag = Tag; // 有时需要用文本框的 Tag 来写入设置
if (string.IsNullOrEmpty(Text))
textBox.Text = _Text;
else
TextChanged?.Invoke(this, null);
if (HintText.Length > 0)
textBox.HintText = HintText;
textBox.SetResourceReference(TextBoxBase.CaretBrushProperty, "ColorBrushGray1");
}
catch (Exception ex)
{
ModBase.Log(
ex,
"初始化可编辑文本框失败(" + (Name ?? "") + "",
ModBase.LogLevel.Feedback,
userSummary: Lang.Text("Application.Control.Error.OperationFailed"));
}
}
private void MyComboBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
isMouseDown = true;
}
private void MyComboBox_PreviewMouseLeftButtonUp(object sender, EventArgs e)
{
isMouseDown = false;
}
// 指向动画
public void RefreshColor()
{
// 判断当前颜色
string foreColorName;
string backColorName;
int time;
if (IsEnabled)
{
if (isMouseDown || IsDropDownOpen ||
(IsEditable && ((MyTextBox)Template.FindName("PART_EditableTextBox", this)).IsFocused))
{
foreColorName = "ColorBrush3";
backColorName = "ColorBrush7";
time = 10;
}
else if (IsMouseOver)
{
foreColorName = "ColorBrush4";
backColorName = "ColorBrush7";
time = 100;
}
else
{
foreColorName = "ColorBrushBg0";
backColorName = "ColorBrushHalfWhite";
time = 100;
}
}
else
{
foreColorName = "ColorBrushGray5";
backColorName = "ColorBrushGray6";
time = 200;
}
// 触发颜色动画
if (IsLoaded && ModAnimation.AniControlEnabled == 0) // 防止默认属性变更触发动画
{
// 有动画
ModAnimation.AniStart(
new[]
{
ModAnimation.AaColor(this, ForegroundProperty, foreColorName, time),
ModAnimation.AaColor(this, BackgroundProperty, backColorName, time)
}, "MyComboBox Color " + Uuid);
}
else
{
// 无动画
ModAnimation.AniStop("MyComboBox Color " + Uuid);
SetResourceReference(ForegroundProperty, foreColorName);
SetResourceReference(BackgroundProperty, backColorName);
}
}
private void MyComboBox_DropDownOpened(object sender, EventArgs e)
{
realWidth = Width;
if (DropDownWidthSync)
Width = ActualWidth;
try
{
var popup = (Grid)Template.FindName("PanPopup", this);
popup.Opacity = ModMain.frmMain.Opacity;
if (!DropDownWidthSync)
popup.MinWidth = ActualWidth;
}
catch (Exception ex)
{
ModBase.Log(
ex,
"设置下拉框属性失败",
ModBase.LogLevel.Feedback,
userSummary: Lang.Text("Application.Control.Error.OperationFailed"));
}
}
private void MyComboBox_DropDownClosed(object sender, EventArgs e)
{
Width = realWidth;
}
private void MyComboBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (isTextChanging || !IsEditable)
return;
if (SelectedItem is null || Text == SelectedItem.ToString()) return;
{
var rawText = Text;
var rawSelectionStart = textBox.SelectionStart;
isTextChanging = true;
SelectedItem = null;
Text = rawText;
textBox.SelectionStart = rawSelectionStart;
isTextChanging = false;
}
}
// 用于 ItemsSource 的自定义容器
protected override DependencyObject GetContainerForItemOverride()
{
return new MyComboBoxItem();
}
private void MyComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (IsLoaded && ModAnimation.AniControlEnabled == 0) ModMain.RaiseCustomEvent(this);
}
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is MyComboBoxItem || base.IsItemItsOwnContainerOverride(item);
}
}