私は、バックスラッシュ(\)文字を使用してタグを階層構造にすることができるアプリケーションがあります。DynamicData:TransformToTree
例えば、
Country\Canada\Alberta
Country\Canada\British Columbia
Country\USA\California
Country\USA\Texas
はユーザーインターフェイスになります。
Country
Canada
Alberta
British Columbia
USA
California
Texas
データベースでは、データベースに文字列として格納され、TagDto
としてクライアントに返されます。私はこれを達成するために次のことを試みました。
public class TagDto
{
public int Id { get; set; }
public string Name { get; set; }
}
public class TagLeaf
{
public string Id { get; }
public string ParentId { get; }
public int TagId { get; }
public string Name { get; }
public TagLeaf(string id, string parentId, int tagId, string name)
{
Id = id;
ParentId = parentId;
TagId = tagId;
Name = name;
}
// IEquatable implemented on Id property.
}
public class TagsViewModel : ReactiveObject
{
private IDisposable TagsSubscription { get; }
public SourceCache<TagDto, string> Tags { get } = new SourceCache<TagDto, string>(t => t.Id);
private readonly ReadOnlyObservableCollection<TagLeafViewModel> _tagTree;
public ReadOnlyObservableCollection<TagLeafViewModel> TagTree => _tagTree;
public ReactiveCommand AddBelgium { get; }
public TagsViewModel()
{
AddBelgium = ReactiveCommand.Create(() =>
Tags.AddOrUpdate(new TagDto {Id = 5, Name = @"Country\Belgium"});
// this comes from an web service normally.
Tags.AddOrUpdate(new[] {
new TagDto {Id = 1, Name = @"Country\Canada\Alberta"},
new TagDto {Id = 2, Name = @"Country\Canada\British Columbia"},
new TagDto {Id = 3, Name = @"Country\USA\California"},
new TagDto {Id = 4, Name = @"Country\USA\Texas"}
});
TagsSubscription = Tags
.Connect()
.TransformMany(dto =>
{
var names = dto.Name.Split(new[] {'\\'}, StringSplitOptions.RemoveEmptyEntries);
var results = new TagLeaf[names.Length];
var parentId = "";
for (var i = 0; i < names.Length; i++)
{
var name = names[i];
var id = $"{parentId}{name}\\";
results[i] = new TagLeaf(id, parentId, dto.Id, name);
parentId = id;
}
return results;
}, leaf => leaf.Id)
.TransformToTree(leaf => leaf.ParentId)
.Transform(leaf => new TagLeafViewModel(leaf))
.Sort(SortExpressionComparer<TagLeafViewModel>.Ascending(vm => vm.Name))
.Bind(out _tagTree)
.Subscribe();
}
}
public class TagLeafViewModel : ReactiveObject
{
private readonly ReadOnlyObservableCollection<TagLeafViewModel> _children;
public ReadOnlyObservableCollection<TagLeafViewModel> Children => _children;
private string _name;
public string Name
{
get => _name;
set => this.RaiseAndSetIfChanged(ref _name, value);
}
public TagLeafViewModel(Node<TagLeaf, string> node)
{
Name = node.Item.Name;
ChildrenSubscription = node.Children
.Connect()
.Transform(n => new TagLeafViewModel(n))
.Sort(SortExpressionComparer<TagLeafViewModel>.Ascending(vm => vm.Name))
.Bind(out _children)
.Subscribe();
}
}
// TagsView.xaml
<StackPanel>
<Button x:Name="AddBelgiumButton" Content="Add Belgium"/>
<telerik:RadTreeView x:Name="TagTreeView">
<telerik:RadTreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</telerik:RadTreeView.ItemTemplate>
</telerik:RadtreeView>
</StackPanel>
// TagsView.xaml.cs constructor
public TagsView()
{
...
this.WhenActivated(d =>
{
d(this.AddBelgiumButton.Events().Click.Select(x => Unit.Default).InvokeCommand(ViewModel, vm => vm.AddBelgium));
d(this.OneWayBind(ViewModel, vm => vm.TagTree, v => v.TagTreeView.ItemsSource));
});
}
は、しかし、これは私がCountry
を拡張し、ではなく、国の下に新しいノードとしてツリーにこの挿入を見ての、ベルギー [追加]をクリックした場合、私が期待するようツリーを生成します - それは、全国のノードを縮小します。
新しいタグを追加すると、新しいTagLeaf
が2つ追加され、TramsformToTree
にストリーミングされます。 1つは国、もう1つはベルギーのため、なぜ国ノードを更新しているのか理解していますが、どのように克服できるかはわかりません。
[mcve]を提供する必要があります。 – Enigmativity
あなたは正しいですが、少し曖昧でした。私はこれがより良いと思う。 – Dan