feat: implement part type management and searchable combo box in property editor
This commit is contained in:
parent
f13d646f7d
commit
0d55a38c86
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"dotnet.preferCSharpExtension": true
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Laservall.Solidworks.Common
|
||||
{
|
||||
public class PartTypeItem
|
||||
{
|
||||
[JsonProperty("type_id")]
|
||||
public string TypeId { get; set; }
|
||||
|
||||
[JsonProperty("parent_type_id")]
|
||||
public string ParentTypeId { get; set; }
|
||||
|
||||
[JsonProperty("code")]
|
||||
public string Code { get; set; }
|
||||
|
||||
[JsonProperty("type_name")]
|
||||
public string TypeName { get; set; }
|
||||
|
||||
[JsonProperty("type_key")]
|
||||
public string TypeKey { get; set; }
|
||||
|
||||
[JsonProperty("is_child")]
|
||||
public string IsChild { get; set; }
|
||||
|
||||
public string DisplayText => $"{Code} - {TypeName}";
|
||||
|
||||
public override string ToString() => DisplayText;
|
||||
}
|
||||
|
||||
public static class PLMService
|
||||
{
|
||||
private const string PartTypeSearchUrl = "http://10.0.0.155:9992/api/PLM/PartType/Search";
|
||||
private static readonly HttpClient _httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
|
||||
|
||||
private static List<PartTypeItem> _cachedPartTypes;
|
||||
private static readonly object _lock = new object();
|
||||
|
||||
public static List<PartTypeItem> CachedPartTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _cachedPartTypes ?? new List<PartTypeItem>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<List<PartTypeItem>> SearchPartTypesAsync(string code = "", string name = "")
|
||||
{
|
||||
try
|
||||
{
|
||||
var requestBody = new { code = code ?? "", name = name ?? "" };
|
||||
var json = JsonConvert.SerializeObject(requestBody);
|
||||
var content = new StringContent(json, Encoding.UTF8, "application/json-patch+json");
|
||||
|
||||
var response = await _httpClient.PostAsync(PartTypeSearchUrl, content).ConfigureAwait(false);
|
||||
var responseText = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
Debug.WriteLine($"PLM PartType/Search failed: {(int)response.StatusCode} {responseText}");
|
||||
return new List<PartTypeItem>();
|
||||
}
|
||||
|
||||
return JsonConvert.DeserializeObject<List<PartTypeItem>>(responseText)
|
||||
?? new List<PartTypeItem>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"PLM PartType/Search error: {ex.Message}");
|
||||
return new List<PartTypeItem>();
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task LoadAndCachePartTypesAsync()
|
||||
{
|
||||
var items = await SearchPartTypesAsync("", "").ConfigureAwait(false);
|
||||
lock (_lock)
|
||||
{
|
||||
_cachedPartTypes = items;
|
||||
}
|
||||
Debug.WriteLine($"PLM PartTypes loaded: {items.Count} items");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
using HandyControl.Controls;
|
||||
using HandyControl.Controls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Laservall.Solidworks.Common
|
||||
{
|
||||
|
|
@ -35,7 +35,7 @@ namespace Laservall.Solidworks.Common
|
|||
{
|
||||
public override FrameworkElement CreateElement(PropertyItem propertyItem)
|
||||
{
|
||||
var comboBox = new ComboBox();
|
||||
var comboBox = new System.Windows.Controls.ComboBox();
|
||||
comboBox.IsEditable = true;
|
||||
var items = ComboBoxDataRegistry.GetItems(propertyItem.DisplayName);
|
||||
comboBox.ItemsSource = items;
|
||||
|
|
@ -49,29 +49,109 @@ namespace Laservall.Solidworks.Common
|
|||
|
||||
public override DependencyProperty GetDependencyProperty()
|
||||
{
|
||||
return ComboBox.SelectedItemProperty;
|
||||
return System.Windows.Controls.ComboBox.SelectedItemProperty;
|
||||
}
|
||||
}
|
||||
|
||||
public class CategoryComboxPropertyEditor : PropertyEditorBase
|
||||
{
|
||||
private static List<PartTypeItem> _allPartTypes = new List<PartTypeItem>();
|
||||
|
||||
public static void SetPartTypes(List<PartTypeItem> items)
|
||||
{
|
||||
_allPartTypes = items ?? new List<PartTypeItem>();
|
||||
}
|
||||
|
||||
public override FrameworkElement CreateElement(PropertyItem propertyItem)
|
||||
{
|
||||
var comboBox = new ComboBox();
|
||||
comboBox.IsEditable = true;
|
||||
var items = ComboBoxDataRegistry.GetItems(propertyItem.DisplayName);
|
||||
comboBox.ItemsSource = items;
|
||||
comboBox.SelectedItem = propertyItem.Value?.ToString();
|
||||
var comboBox = new System.Windows.Controls.ComboBox
|
||||
{
|
||||
IsEditable = true,
|
||||
IsTextSearchEnabled = false
|
||||
};
|
||||
|
||||
var allItems = _allPartTypes;
|
||||
|
||||
comboBox.ItemsSource = allItems;
|
||||
comboBox.DisplayMemberPath = "DisplayText";
|
||||
comboBox.SelectedValuePath = "Code";
|
||||
|
||||
var currentCode = propertyItem.Value?.ToString();
|
||||
if (!string.IsNullOrEmpty(currentCode))
|
||||
{
|
||||
var match = allItems.FirstOrDefault(x =>
|
||||
string.Equals(x.Code, currentCode, StringComparison.OrdinalIgnoreCase));
|
||||
if (match != null)
|
||||
{
|
||||
comboBox.SelectedItem = match;
|
||||
}
|
||||
}
|
||||
|
||||
bool suppressFilter = false;
|
||||
|
||||
comboBox.SelectionChanged += (s, e) =>
|
||||
{
|
||||
propertyItem.Value = comboBox.SelectedItem;
|
||||
if (comboBox.SelectedItem is PartTypeItem selected)
|
||||
{
|
||||
propertyItem.Value = selected.Code;
|
||||
}
|
||||
};
|
||||
|
||||
comboBox.Loaded += (s, e) =>
|
||||
{
|
||||
var textBox = comboBox.Template.FindName("PART_EditableTextBox", comboBox) as TextBox;
|
||||
if (textBox == null) return;
|
||||
|
||||
textBox.TextChanged += (s2, e2) =>
|
||||
{
|
||||
if (suppressFilter) return;
|
||||
|
||||
var text = textBox.Text;
|
||||
if (string.IsNullOrEmpty(text))
|
||||
{
|
||||
comboBox.ItemsSource = allItems;
|
||||
}
|
||||
else
|
||||
{
|
||||
var lower = text.ToLowerInvariant();
|
||||
var filtered = allItems.Where(x =>
|
||||
(x.Code != null && x.Code.ToLowerInvariant().Contains(lower)) ||
|
||||
(x.TypeName != null && x.TypeName.ToLowerInvariant().Contains(lower))
|
||||
).ToList();
|
||||
comboBox.ItemsSource = filtered;
|
||||
}
|
||||
|
||||
suppressFilter = true;
|
||||
comboBox.IsDropDownOpen = true;
|
||||
textBox.Text = text;
|
||||
textBox.CaretIndex = text.Length;
|
||||
suppressFilter = false;
|
||||
};
|
||||
};
|
||||
|
||||
comboBox.DropDownClosed += (s, e) =>
|
||||
{
|
||||
if (comboBox.SelectedItem is PartTypeItem selected)
|
||||
{
|
||||
suppressFilter = true;
|
||||
var textBox = comboBox.Template.FindName("PART_EditableTextBox", comboBox) as TextBox;
|
||||
if (textBox != null)
|
||||
{
|
||||
textBox.Text = selected.DisplayText;
|
||||
textBox.CaretIndex = textBox.Text.Length;
|
||||
}
|
||||
suppressFilter = false;
|
||||
|
||||
comboBox.ItemsSource = allItems;
|
||||
}
|
||||
};
|
||||
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
public override DependencyProperty GetDependencyProperty()
|
||||
{
|
||||
return ComboBox.SelectedItemProperty;
|
||||
return System.Windows.Controls.ComboBox.SelectedValueProperty;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@
|
|||
<Compile Include="AppDomainDllLoader.cs" />
|
||||
<Compile Include="Common\PLMConfig.cs" />
|
||||
<Compile Include="Common\PropertyEditor.cs" />
|
||||
<Compile Include="Common\PartTypeService.cs" />
|
||||
<Compile Include="Common\SM4Helper.cs" />
|
||||
<Compile Include="Common\ViewModelBase.cs" />
|
||||
<Compile Include="Common\RelayCommand.cs" />
|
||||
|
|
@ -169,8 +170,8 @@
|
|||
<Import Project="packages\Xarial.XCad.SolidWorks.0.8.2\build\Xarial.XCad.SolidWorks.targets" Condition="Exists('packages\Xarial.XCad.SolidWorks.0.8.2\build\Xarial.XCad.SolidWorks.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
|
||||
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用"NuGet 程序包还原"可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('packages\Xarial.XCad.SolidWorks.0.8.2\build\Xarial.XCad.SolidWorks.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Xarial.XCad.SolidWorks.0.8.2\build\Xarial.XCad.SolidWorks.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using HandyControl.Controls;
|
||||
using HandyControl.Controls;
|
||||
using Laservall.Solidworks.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
|
@ -168,6 +168,21 @@ namespace Laservall.Solidworks.Model
|
|||
}
|
||||
}
|
||||
|
||||
private string _partType;
|
||||
[Category("零件属性")]
|
||||
[DisplayName("零件类型")]
|
||||
[Editor(typeof(SearchableComboBoxPropertyEditor), typeof(SearchableComboBoxPropertyEditor))]
|
||||
public string PartType
|
||||
{
|
||||
get => _partType;
|
||||
set
|
||||
{
|
||||
if (_partType == value) return;
|
||||
_partType = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _purCheck;
|
||||
[Category("零件属性")]
|
||||
[DisplayName("采购检验")]
|
||||
|
|
@ -211,4 +226,4 @@ namespace Laservall.Solidworks.Model
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ using Laservall.Solidworks.Model;
|
|||
using SolidWorks.Interop.sldworks;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using Xarial.XCad;
|
||||
using Xarial.XCad.Documents;
|
||||
|
|
@ -37,8 +38,16 @@ namespace Laservall.Solidworks.Pane
|
|||
set => Set(ref _versionText, value);
|
||||
}
|
||||
|
||||
private bool _isLoadingPartTypes;
|
||||
public bool IsLoadingPartTypes
|
||||
{
|
||||
get => _isLoadingPartTypes;
|
||||
set => Set(ref _isLoadingPartTypes, value);
|
||||
}
|
||||
|
||||
public ICommand SaveCommand { get; }
|
||||
public ICommand ResetCommand { get; }
|
||||
public ICommand RefreshPartTypesCommand { get; }
|
||||
|
||||
public PartPropPaneViewModel()
|
||||
{
|
||||
|
|
@ -46,6 +55,45 @@ namespace Laservall.Solidworks.Pane
|
|||
|
||||
SaveCommand = new RelayCommand(ExecuteSave, CanSave);
|
||||
ResetCommand = new RelayCommand(ExecuteReset, CanReset);
|
||||
RefreshPartTypesCommand = new RelayCommand(async _ => await LoadPartTypesAsync());
|
||||
|
||||
// 异步加载零件类型数据
|
||||
Task.Run(async () => await LoadPartTypesAsync());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从PLM API加载零件类型数据
|
||||
/// </summary>
|
||||
private async Task LoadPartTypesAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
IsLoadingPartTypes = true;
|
||||
StatusText = "正在加载零件类型...";
|
||||
|
||||
// 调用PLM API获取零件类型
|
||||
var partTypes = await PartTypeService.GetAllAsync();
|
||||
|
||||
if (partTypes.Count > 0)
|
||||
{
|
||||
// 注册到可搜索ComboBox编辑器
|
||||
SearchableComboBoxPropertyEditor.RegisterPartTypes("零件类型", partTypes);
|
||||
StatusText = $"已加载 {partTypes.Count} 个零件类型";
|
||||
}
|
||||
else
|
||||
{
|
||||
StatusText = "未找到零件类型数据";
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"加载零件类型失败: {ex.Message}");
|
||||
StatusText = "加载零件类型失败";
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsLoadingPartTypes = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnSelectionChanged(IXDocument doc, IXSelObject selObject)
|
||||
|
|
|
|||
Loading…
Reference in New Issue