私はバインドされているオブジェクトのタイプに基づいて、特定のUserControlタイプ(texbox、コンボボックス、カスタムコントロール、または別のビューなど)を表示するために、ViewのDataTemplateを作成しようとしています。バインドされたオブジェクトの型に従ってDataTemplateを動的に変更する方法はありますか。
私は、次のMVVMフレームワークを持っている:
FieldView
はFieldPresenter
のインスタンスに結ばれ、「ラベル」プロパティ、およびユーザーコントロールまたはタイプに基づいた値(のための別のビューの<Textblock />
が表示されるはずですその値はPresenterのValueプロパティに設定されています)。現在、私は第二の部分が働いていません。私は必要なもののためのWPFテンプレートを書く方法を理解できません。
のViewModel:
public class FieldPresenter : Observable<object>, IFieldPresenter, INotifyPropertyChanged
{
public FieldPresenter() { }
public FieldPresenter(object value)
{
Value = value;
}
object IFieldPresenter.Value
{
get
{
return base.Value;
}
set
{
base.Value = value;
OnPropertyChanged("Value");
}
}
private string _label;
public virtual string Label
{
get
{
return _label;
}
private set
{
_label = value;
OnPropertyChanged("Label");
}
}
}
ビュー:
<UserControl x:Class="My.Views.FieldView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ViewModels="clr-namespace:My.ViewModels"
mc:Ignorable="d"
d:DesignHeight="24" d:DesignWidth="100">
<UserControl.DataContext>
<ViewModels:FieldPresenter/>
</UserControl.DataContext>
<UserControl.Template>
<ControlTemplate>
<Grid Margin="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Key" />
</Grid.ColumnDefinitions>
<StackPanel Margin="0,0,0,0" HorizontalAlignment="Stretch" Width="{Binding RelativeSource={RelativeSource AncestorType=Grid}, Path=ActualWidth}">
<TextBlock Text="{Binding Label}" FontWeight="Bold" Height="32" HorizontalAlignment="Stretch"/>
<TextBox Text="{Binding Value}" Height="Auto" HorizontalAlignment="Stretch"/>
</StackPanel>
</Grid>
</ControlTemplate>
</UserControl.Template>
</UserControl>
私がやろうとしていることも、可能であるならば、私は好奇心が強い、または私はプレゼンターのviewmodelリターンを作ることによって、それを回避することができる場合オブジェクト値ではなくUserControlを使用し、Presenterがオブジェクト型からUserControl Typeを解析するようにしましたが、Presenterがコントロールをインスタンス化する必要はありません(つまり、技術的にはバインドされていないビューです)。私はIViewAs<controlType> { controlType View { get; } }
のようなインターフェイスを作っていいですか?
上記のスクリプトの<TextBox Text="{Binding Value}" />
を、データバインドされたオブジェクトの型に基づいたUserControlのテンプレートに置き換えるとどうなりますか?
ContentTemplateSelector
たい
'ContentTemplateSelector'がこの回答に完全に不要である' DataType'バインディングが宣言されていないので、それはここで必要なの唯一の理由があります正しく。リソースブロックから 'ContentTemplateSelector'を削除し、' ContentTemplateSelector = "{StaticResource myTemplateSelector}" 'を削除し、' '' DataTemplate DataType = "{ x:Key = "SphereTemplate" DataType = "local:Sphere">>をに変更します。コードはまったく同じように動作します。 –
あなたは正しいですが、そうすることで常に同じテンプレートを同じタイプに何度も繰り返し割り当てます。たとえば、OPは特定のメカニズムを使って特定のテンプレート名を指定でき、同じテンプレートに対して異なるテンプレートを割り当てることができます(彼はそのようなものが必要です):) – Aybe
今あなたのVMをきれいに保つことができます:) – Aybe