Ich würde vorschlagen, anders zu gehen. Anstatt über das dynamische Hinzufügen von Eigenschaften zu einer Ansicht/einem Modell nachzudenken, würde ich über das Hinzufügen von Informationen über diese Eigenschaften zu einer Liste auf dem Ansichtsmodell nachdenken. Diese Liste wäre dann an eine ItemsControl
mit einer Vorlage gebunden, die wie eine TextBox
aussieht.
Ihr Ansichtsmodell hätte also eine Eigenschaft für das "Ding", das Sie untersuchen möchten. Verwenden Sie im Setter für diese Eigenschaft reflection, um die Eigenschaften aufzulisten, an denen Sie interessiert sind, und fügen Sie der Liste der Eigenschaften mit der Bindung eine Instanz einer beliebigen Klasse FieldInfo
hinzu (die Sie erstellen).
Dies hat den Vorteil, dass auch alle MVVM-kompatiblen Geräte kompatibel sind. Es ist nicht erforderlich, Steuerelemente mit Ihrem eigenen Code dynamisch zu erstellen.
Das folgende Beispiel verwendet meine eigene MVVM-Bibliothek (als nuget Paket) statt caliburn.micro, aber es sollte ähnlich genug sein, um die Grundidee zu folgen. Der vollständige Quellcode des Beispiels kann von this BitBucket repo heruntergeladen werden.
Wie Sie in den enthaltenen Screenshots sehen können, werden die Suchfelder dynamisch in der Ansicht ohne Code in der Ansicht erstellt. Alles wird auf dem Viewmodel gemacht. Dies ermöglicht Ihnen auch einen einfachen Zugriff auf die Daten, die der Benutzer eingibt.
Der Blick-Modell:
namespace DynamicViewExample
{
class MainWindowVm : ViewModel
{
public MainWindowVm()
{
Fields = new ObservableCollection<SearchFieldInfo>();
SearchableTypes = new ObservableCollection<Type>()
{
typeof(Models.User),
typeof(Models.Widget)
};
SearchType = SearchableTypes.First();
}
public ObservableCollection<Type> SearchableTypes { get; }
public ObservableCollection<SearchFieldInfo> Fields { get; }
private Type _searchType;
public Type SearchType
{
get { return _searchType; }
set
{
_searchType = value;
Fields.Clear();
foreach (PropertyInfo prop in _searchType.GetProperties())
{
var searchField = new SearchFieldInfo(prop.Name);
Fields.Add(searchField);
}
}
}
private ICommand _searchCommand;
public ICommand SearchCommand
{
get { return _searchCommand ?? (_searchCommand = new SimpleCommand((obj) =>
{
WindowManager.ShowMessage(String.Join(", ", Fields.Select(f => $"{f.Name}: {f.Value}")));
})); }
}
}
}
Die SearchFieldInfo
Klasse:
namespace DynamicViewExample
{
public class SearchFieldInfo
{
public SearchFieldInfo(string name)
{
Name = name;
}
public string Name { get; }
public string Value { get; set; } = "";
}
}
Aussicht:
<Window
x:Class="DynamicViewExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:DynamicViewExample"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="525"
Height="350"
d:DataContext="{d:DesignInstance local:MainWindowVm}"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ComboBox
Grid.Row="0"
ItemsSource="{Binding Path=SearchableTypes}"
SelectedItem="{Binding Path=SearchType}" />
<ItemsControl Grid.Row="1" ItemsSource="{Binding Path=Fields}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Name}" />
<TextBox Width="300" Text="{Binding Path=Value}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button Grid.Row="2" Command="{Binding Path=SearchCommand}">Search</Button>
</Grid>
</Window>
Die Modellklassen:
class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string PhoneNumber { get; set; }
public string Id { get; set; }
}
class Widget
{
public string ModelNumber { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
Also im Grunde wollen Sie einen Text pro öffentlichem Eigentum des Typ T generieren? – mm8
@ mm8 Ja, Sie haben Recht! – Rahul
Ich denke, Sie wissen, wie Sie den DataContext der Sicht auf ein SearchViewModel setzen? –
mm8