3

サンプルの MVVM WPF アプリケーションがあり、動的に読み込まれたモデルの DataTemplates の作成に問題があります。説明してみましょう:

モデルの一部として次の単純化されたクラスがあり、動的にロードしています

public class Relationship
{
    public string Category { get; set; }
    public ParticipantsType Participants { get; set; }
}

public class ParticipantsType
{
    public ObservableCollection<ParticipantType> Participant { get; set; }
}

public class ParticipantType
{

}

public class EmployeeParticipant : ParticipantType
{
    public EmployeeIdentityType Employee { get; set; }
}

public class DepartmentParticipant : ParticipantType
{
    public DepartmentIdentityType Department { get; set; }
}

public class EmployeeIdentityType
{
    public string ID { get; set; }
}

public class DepartmentIdentityType
{
    public string ID { get; set; }
}

これが私のビューモデルの外観です。Modelモデルを公開する汎用オブジェクト プロパティを作成しました。

    public class MainViewModel : ViewModelBase<MainViewModel>
{
    public MainViewModel()
    {
        SetMockModel();
    }

    private void SetMockModel()
    {
        Relationship rel = new Relationship();
        rel.Category = "213";
        EmployeeParticipant emp = new EmployeeParticipant();
        emp.Employee = new EmployeeIdentityType();
        emp.Employee.ID = "222";
        DepartmentParticipant dep = new DepartmentParticipant();            
        dep.Department = new DepartmentIdentityType();
        dep.Department.ID = "444";
        rel.Participants = new ParticipantsType() { Participant = new ObservableCollection<ParticipantType>() };
        rel.Participants.Participant.Add(emp);
        rel.Participants.Participant.Add(dep);            
        Model = rel;
    }

    private object _Model;
    public object Model
    {
        get { return _Model; }
        set
        {
            _Model = value;
            NotifyPropertyChanged(m => m.Model);
        }
    }
}

次に、ListBox を作成して、特に参加者コレクションを表示しようとしました。

<ListBox ItemsSource="{Binding Path=Model.Participants.Participant}">
<ListBox.ItemTemplate>
    <DataTemplate>
        <StackPanel>
            <Expander Header="IdentityFields">
            <!-- WHAT TO PUT HERE IF PARTICIPANTS HAVE DIFFERENT PROPERTY NAMES -->
            </Expander>
        </StackPanel>
    </DataTemplate>
</ListBox.ItemTemplate>

問題は:

  1. 両方のタイプの ParticipantTypes を処理できるテンプレートを作成する方法がわかりません。この場合、EmployeeParticipant または DepartmentParticipant を使用できるため、それに応じて、データ バインディング パスが設定されるEmployeeか、Departmentそれに応じてプロパティが設定されます。
  2. 各タイプ (x:Type EmployeeParticipant など) の DataTemplate を作成することについてですが、問題は、モデル内のクラスが実行時に動的に読み込まれるため、VisualStudio が現在のソリューションにそれらのタイプが存在しないと不平を言うことです。

具体的な型がコンパイル時に不明で、実行時にしかわからない場合、このデータを ListBox で表現するにはどうすればよいでしょうか?

編集:私のテスト ViewModel クラスを追加しました

4

3 に答える 3

2

DataTemplateタイプごとにを作成することもできますが、DataType宣言を使用して自動的に解決する代わりに、受信データ項目を基本クラスにキャストしてプロパティを確認するなど、DataTemplateSelectorテンプレートごとにプロパティを使用してを作成できます(XAMLで割り当てられます)。StaticResource実行時に使用するテンプレートを決定します。そのセレクターをに割り当てると、ListBox.ItemTemplateSelector同じような動作DataTypeが得られます。

于 2013-02-12T15:55:38.487 に答える
0

次のように変更ListBoxします。

        <ListBox ItemsSource="{Binding Model.Participants.Participant}">
            <ListBox.Resources>
                <DataTemplate DataType="{x:Type loc:DepartmentParticipant}">
                    <Grid>
                        <TextBlock Text="{Binding Department.ID}"/>
                    </Grid>
                </DataTemplate>
                <DataTemplate DataType="{x:Type loc:EmployeeParticipant}">
                    <Grid>
                        <TextBlock Text="{Binding Employee.ID}"/>
                    </Grid>
                </DataTemplate>
            </ListBox.Resources>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <Expander Header="IdentityFields">
                            <!-- WHAT TO PUT HERE IF PARTICIPANTS HAVE DIFFERENT PROPERTY NAMES -->
                            <ContentPresenter Content="{Binding }"/>
                        </Expander>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

DepartmentParticipant編集:locは、とが存在する名前空間を指しますEmployeeParticipant。名前空間の追加に精通していることを願っています。

于 2013-02-12T16:45:45.400 に答える
0

それは良いビューモデルではありません。ビューモデルは、ビジネス中心ではなく、ビュー中心である必要があります。したがって、視覚的な観点から 4 つのケースすべてを処理できるクラスを作成し、ビジネス クラスをそのビューモデルに橋渡しします。


編集:

コードの作業:

<ListBox ItemsSource="{Binding Path=Model.Participants}">
<ListBox.ItemTemplate>
    <DataTemplate>
        <StackPanel>
            <Expander Header="IdentityFields">
                <TextBlock Text={Binding Id} />
                <TextBlock Text={Binding Name} />
            </Expander>
        </StackPanel>
    </DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

バインディングを変更しましたが、それは間違いだったと思いますか?

Participant の ViewModel を作成します。

public class Participant_VM : ViewModelBase
{

    private string _name = string.Empty;
    public string Name
    {
        get
        {
            return _name ;
        }

        set
        {
            if (_name == value)
            {
                return;
            }
            _name = value;
            RaisePropertyChanged(() => Name);
        }

    private string _id= string.Empty;
    public string Id
    {
        get
        {
            return _id;
        }

        set
        {
            if (_id== value)
            {
                return;
            }
            _id = value;
            RaisePropertyChanged(() => Id);
        }

    }
}
于 2013-02-12T15:58:04.287 に答える