using CommunityToolkit.Mvvm.ComponentModel; using OpenTap.Addin; using OpenTapEditor.Util; using System.Collections.ObjectModel; using System.Globalization; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using UILib; namespace OpenTapEditor { public class TestVariableConverter : IValueConverter { public static TestVariableConverter Instance = new TestVariableConverter(); public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is TestVariable tv) { if (parameter?.ToString() == "TypeName") { return tv.IsArray ? $"{tv.Type}[]" : tv.Type.ToString(); } if (parameter?.ToString() == "CanEdit") { return !tv.IsArray && tv.Type != TestVariableType.Container && tv.Type != TestVariableType.Refrence; } } return value; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return value; } } public partial class TestVariableWrapper : ObservableObject { [ObservableProperty] private TestVariable value; [ObservableProperty] private TestVariable parent; private bool ValueCanEdit => Value?.IsArray == false; private bool NameCanEdit => Value?.IsArray == true; } public class TestVariableMenuItem : MenuItem { public IEnumerable Source { get; set; } public TestVariable Variable { get; set; } public TestVariable Parent { get; set; } public bool TargetIsArray { get; set; } public TestVariableType TargetType { get; set; } } /// /// VariableTree.xaml 的交互逻辑 /// public partial class VariableTree : UserControl { public VariableTree() { InitializeComponent(); BindingOperations.SetBinding(fileGlobalView, TreeListView.ItemsSourceProperty, new Binding(nameof(Datasource)) { Source = this, Mode = BindingMode.TwoWay, }); } public static DependencyProperty DatasourceProperty = DependencyProperty.Register( "Datasource", typeof(ObservableCollection), typeof(VariableTree), new PropertyMetadata(null) ); public string Prefix { get; set; } public ObservableCollection Datasource { get => (ObservableCollection)GetValue(DatasourceProperty); set { SetValue(DatasourceProperty, value); } } private void OnPreviewMouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { DependencyObject source = e.OriginalSource as DependencyObject; while (source != null && source.GetType() != typeof(TreeListViewItem)) { source = System.Windows.Media.VisualTreeHelper.GetParent(source); } if (source != null) { TreeListViewItem item = source as TreeListViewItem; item.Focus(); var variable = item.DataContext; CreateContextMenu(item, variable); } else { CreateContextMenu(null, null); } } public List RefreshMenuItems(TestVariable parent) { var allSteps = StepTypeLoader.Steps; var StepMenuItems = new List(allSteps.Count); foreach (TestVariableType type in Enum.GetValues(typeof(TestVariableType))) { TestVariableMenuItem menuItem = new TestVariableMenuItem(); menuItem.Header = type.ToString(); menuItem.Click += MenuItem_Click; menuItem.TargetIsArray = false; menuItem.TargetType = type; menuItem.Parent = parent; StepMenuItems.Add(menuItem); } var arrItem = new MenuItem(); arrItem.Header = "Array Of..."; foreach (TestVariableType type in Enum.GetValues(typeof(TestVariableType))) { TestVariableMenuItem menuItem = new TestVariableMenuItem(); menuItem.Header = type.ToString(); menuItem.Click += MenuItem_Click; menuItem.TargetIsArray = true; menuItem.TargetType = type; menuItem.Parent = parent; arrItem.Items.Add(menuItem); } StepMenuItems.Add(arrItem); return StepMenuItems; } /// /// 显示菜单 /// /// private void CreateContextMenu(TreeListViewItem item, object obj) { var v = obj as TestVariable; ContextMenu contextMenu = new ContextMenu(); contextMenu.Closed += ContextMenu_Closed; var parent = item?.parent?.DataContext as TestVariable; TestVariableMenuItem menuItem = new TestVariableMenuItem(); if (v == null) { menuItem.Header = "插入"; foreach (var i in RefreshMenuItems(null)) { menuItem.Items.Add(i); } contextMenu.Items.Add(menuItem); } else if (v.IsArray) { menuItem.Header = "插入元素"; menuItem.Variable = v; menuItem.Parent = v; menuItem.Click += MenuItem_Click; contextMenu.Items.Add(menuItem); } else if (v.Type == TestVariableType.Container) { menuItem.Header = "插入"; foreach (var i in RefreshMenuItems(v)) { menuItem.Items.Add(i); } contextMenu.Items.Add(menuItem); } if (v != null) { menuItem = new TestVariableMenuItem(); menuItem.Header = "删除"; menuItem.Click += Delete_Click; menuItem.Variable = v; menuItem.Tag = item; contextMenu.Items.Add(menuItem); menuItem = new TestVariableMenuItem(); menuItem.Header = "复制名称"; menuItem.Click += CopyName_Click; menuItem.Tag = item; contextMenu.Items.Add(menuItem); } this.fileGlobalView.ContextMenu = contextMenu; } private void ContextMenu_Closed(object sender, RoutedEventArgs e) { this.fileGlobalView.ContextMenu = null; } private void MenuItem_Click(object sender, RoutedEventArgs e) { TestVariableMenuItem item = sender as TestVariableMenuItem; var v = item.Parent; if (v == null) { Datasource.Add(new TestVariable { IsArray = item.TargetIsArray, Type = item.TargetType, Value = item.TargetIsArray ? null : TestVariable.DefaultValue(item.TargetType) }); return; } if (v.IsArray) { v.Children.Add(new TestVariable { Name = $"[{v.Children.Count}]", IsArray = false, Type = v.Type, Value = TestVariable.DefaultValue(v.Type) }); for (int i = 0; i < v.Children.Count; i++) { v.Children[i].Name = $"[{i}]"; } return; } if (v.Type == TestVariableType.Container) { v.Children.Add(new TestVariable { IsArray = item.TargetIsArray, Type = item.TargetType, Value = item.TargetIsArray ? null : TestVariable.DefaultValue(item.TargetType) }); return; } } private void Delete_Click(object sender, RoutedEventArgs e) { var tv = ((TestVariableMenuItem)sender).Variable; var item = ((TestVariableMenuItem)sender).Tag as TreeListViewItem; if (item.parent == null) { Datasource.Remove(tv); } else { var parentData = item.parent.DataContext as TestVariable; parentData.Children.Remove(tv); if (parentData.IsArray) { for (int i = 0; i < parentData.Children.Count; i++) { parentData.Children[i].Name = $"[{i}]"; } } } } private void Button_Click(object sender, RoutedEventArgs e) { var tv = ((Button)sender).Tag as TestVariable; MessageBox.Show(tv.Name); } private void CopyName_Click(object sender, RoutedEventArgs e) { var item = ((TestVariableMenuItem)sender).Tag as TreeListViewItem; var tv = item?.DataContext as TestVariable; string name = ""; while (tv != null) { if (tv.IsArray) { name = tv.Name + name; } else { name = tv.Name + (string.IsNullOrEmpty(name) ? "" : $".{name}"); } item = item.parent; tv = item?.DataContext as TestVariable; } Clipboard.SetText(string.IsNullOrEmpty(Prefix) ? name : $"{Prefix}.{name}"); } } }