いつも活用させていただいております。
早速ですが、タイトルについて相談させてください。
前提・実現したいこと
ある項目定義に合わせてPropertyGridへ表示する項目内容を動的に変化させてデータを登録したい。
※現状は、XceedのPropertyGridで実現を検討しています。
発生している問題・エラーメッセージ
初期値の値が表示されない。また、入力した値がBindingした変数に反映されない。
該当のソースコード
XAML
1<Window x:Class="SensCmdApp.View.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:SensCmdApp.View" 7 mc:Ignorable="d" 8 xmlns:i="http://schemas.microsoft.com/xaml/behaviors" 9 xmlns:rp="clr-namespace:Reactive.Bindings.Interactivity;assembly=ReactiveProperty.WPF" 10 xmlns:vm="clr-namespace:SensCmdApp.ViewModel" 11 xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" xmlns:model="clr-namespace:SensCmdApp.Model" 12 Title="MainWindow" Height="450" Width="800"> 13 14 <Window.DataContext> 15 <vm:MainWindowViewModel /> 16 </Window.DataContext> 17 18 <Grid> 19 <Grid.ColumnDefinitions> 20 <ColumnDefinition MinWidth="100" Width="200" /> 21 <ColumnDefinition Width="5" /> 22 <ColumnDefinition Width="*" /> 23 </Grid.ColumnDefinitions> 24 25 <DockPanel Grid.Column="0" LastChildFill="True" > 26 <TreeView ItemsSource="{Binding CommandTree}" DockPanel.Dock="Top" Margin="5,5,0,5"> 27 28 <i:Interaction.Triggers> 29 <i:EventTrigger EventName="SelectedItemChanged"> 30 <rp:EventToReactiveCommand Command="{Binding SelectionChangedCommand}" /> 31 </i:EventTrigger> 32 </i:Interaction.Triggers> 33 34 <TreeView.ItemTemplate> 35 <HierarchicalDataTemplate ItemsSource="{Binding Children}" > 36 <TextBlock Text="{Binding Name}" /> 37 </HierarchicalDataTemplate> 38 </TreeView.ItemTemplate> 39 40 </TreeView> 41 </DockPanel> 42 43 <GridSplitter Grid.Column="1" Style="{StaticResource VerticalGridSplitter}" /> 44 45 <DockPanel Grid.Column="2" LastChildFill="True"> 46 <Button Content="Test" DockPanel.Dock="Bottom" Height="30" /> 47 <xctk:PropertyGrid DockPanel.Dock="Bottom" ShowSearchBox="False" ShowSortOptions="False" SelectedObject="{Binding CommandProperty.Value, UpdateSourceTrigger=PropertyChanged}" /> 48 </DockPanel> 49 </Grid> 50</Window>
c#
1/// CustomProperty/CustomPropertyDescriptor/CustomObjectConverter 2/// 3using System; 4using System.Collections.Generic; 5using System.Collections.ObjectModel; 6using System.ComponentModel; 7using System.Linq; 8 9namespace SensCmdApp.Model 10{ 11 /// <summary> 12 /// CustomClass (Which is binding to property grid) 13 /// </summary> 14 //[TypeConverter(typeof(CustomObjectConverter))] 15 [TypeConverter(typeof(CustomObjectConverter))] 16 public class CustomObjectType 17 { 18 [Browsable(false)] 19 public string Name { get; set; } 20 [Browsable(false)] 21 public ObservableCollection<CustomProperty> Properties { get; set; } = new ObservableCollection<CustomProperty>(); 22 } 23 /// <summary> 24 /// Custom property class 25 /// </summary> 26 public class CustomProperty 27 { 28 public string Category { get; set; } = string.Empty; 29 public string Name { get; set; } = string.Empty; 30 public object Value { get; set; } = null; 31 public string Description { get; set; } = string.Empty; 32 public bool IsReadOnly { get; set; } = false; 33 public bool IsVisible { get; set; } = true; 34 public Type Type { get; set; } = null; 35 } 36 /// <summary> 37 /// Custom PropertyDescriptor 38 /// </summary> 39 public class CustomPropertyDescriptor : PropertyDescriptor 40 { 41 CustomProperty _prop; 42 43 public CustomPropertyDescriptor(CustomProperty Property, Attribute[] Attributes) : base(Property.Name, Attributes) 44 { 45 _prop = Property; 46 } 47 48 #region PropertyDescriptor specific 49 public override bool CanResetValue(object component) => true; 50 public override Type ComponentType => _prop.Value.GetType(); 51 public override object GetValue(object component) => _prop.Value; 52 public override string Name => _prop.Name; 53 public override string Description => _prop.Description; 54 public override string Category => _prop.Category; 55 public override string DisplayName => _prop.Name; 56 public override bool IsReadOnly => _prop.IsReadOnly; 57 public override void ResetValue(object component) { /* Have to implement */ } 58 public override bool ShouldSerializeValue(object component) => true; 59 public override void SetValue(object component, object value) => _prop.Value = value; 60 public override Type PropertyType => _prop.Value.GetType(); 61 public override bool IsBrowsable => _prop.IsVisible; 62 #endregion 63 } 64 65 public class CustomObjectConverter : ExpandableObjectConverter 66 { 67 public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) 68 { 69 CustomObjectType obj = value as CustomObjectType; 70 List<CustomProperty> customProps = obj?.Properties.ToList(); 71 PropertyDescriptor[] props = new PropertyDescriptor[(customProps == null ? 0 : customProps.Count)]; 72 if (customProps != null) 73 { 74 for (int i = 0; i < customProps.Count; i++) 75 { 76 props[i] = new CustomPropertyDescriptor(customProps[i], attributes); 77 } 78 } 79 80 return new PropertyDescriptorCollection(props); 81 } 82 } 83}
C#
1// ~~ 省略 ~~ 2 3 public ReactiveProperty<CustomObjectType> CommandProperty { get; set; } = new ReactiveProperty<CustomObjectType>(); 4 5 public CustomObjectType GetCommandProperty() 6 { 7 var result = new CustomObjectType(); 8 9 try 10 { 11 var cmd = CommandInfo; 12 13 if (CommandInfo == null) { return null; } 14 15 // Command Information 16 var name = $"{cmd.CommandName}"; 17 var desc = $"{cmd.Summery}\n{cmd.Detail}"; 18 19 result.Name = name; 20 result.Properties.Add(new CustomProperty() { Category = "CommandInformation", Name = "CommandName", Type = typeof(string), Description = desc, Value = cmd.CommandName }); 21 result.Properties.Add(new CustomProperty() { Category = "CommandInformation", Name = "AdjustBlock", Type = typeof(string), Description = desc, Value = cmd.CommandName }); 22 result.Properties.Add(new CustomProperty() { Category = "CommandInformation", Name = "AdjustCode", Type = typeof(string), Description = desc, Value = cmd.CommandName }); 23 24 for (int i = 0; i < cmd.RequestParamNum; i++) 25 { 26 result.Properties.Add(new CustomProperty() { Category = "RequestParameter", Name = $"S{i}", Type = typeof(uint), Description = $"S{i}", Value = 0 }); 27 } 28 29 for (int i = 0; i < cmd.ResponseParamNum; i++) 30 { 31 result.Properties.Add(new CustomProperty() { Category = "ResponseParameter", Name = $"R{i}", Type = typeof(uint), Description = $"R{i}", Value = 0 }); 32 } 33 } 34 catch (Exception) 35 { 36 result = null; 37 } 38 39 CommandProperty.Value = result; 40 return result; 41 }
試したこと
上記を実行することで、動的にProperty自体は表示されるものの、PropertyGrid上に値が表示されない。
また、値をいれても、その値が、「CommandProperty」に反映されない。
※CustomPropertyDescriptor の「SetValue」「GetValue」にブレークポイントをはっても停止されない(実行されていない)
補足情報(FW/ツールのバージョンなど)
Visual Studio 2019
.NET Framework 4.6.1
SetValue/GetValueが呼ばれないことためだとは思うのですが、なぜ呼ばれないのかがわからず。。。
根本的に間違っているような気もするのですが、どこなのかがわからず困っています。
申し訳ありませんが、ご教授お願いしたいと思います。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/08/11 12:44