1

これは、MVVMの使用に関するベストプラクティスのアドバイスに関するものです。

要素がドロップインされたときに、ラップパネルにデータを入力する必要があります。要素は均一ではなく、ラベルまたはテキストボックスのいずれかになります。パラメータの値に応じて、追加される要素は異なります。

私はこれをコードビハインドで行いました。現在、すべてをMVVMモデルに移行する過程にあり、MVVMコアプリンシパルに影響を与えることなくこれを行う方法に固執しています。このコードには、密接に関連するUI要素とロジックコンテンツの両方が含まれています。そして、私は2つをスイートMVVMに分離することができなくなりました。

VMでUI要素を作成し、UIElementタイプのObservableCollectionにデータを入力し、それをitemssourceプロパティにバインドしてみました(その後、wrappanelをリストビューに変更して全体的に有効にしました)。しかし、要素をバインドすると、コードがどのUIelementを理解できるかわからないため、これはうまくいきませんでした。

以下に投稿されているのは、私が分離する必要のあるコードのセクションです。

private void CreateVisulaQueryContent() {

            VisualQueryObject visualQueryData = new VisualQueryObject();

            VisualQueryObject helperVisualQueryObject = DraggedData as    VisualQueryObject;


            //***Taking a copy of the static DraggedData object to be bound

                visualQueryData.ColumnDiscriptor = helperVisualQueryObject.ColumnDiscriptor;

            visualQueryData.ComparedValue = helperVisualQueryObject.ComparedValue;

            visualQueryData.JoinWithColumnDescriptor = helperVisualQueryObject.JoinWithColumnDescriptor;

            visualQueryData.LabelType = helperVisualQueryObject.LabelType;
            visualQueryData.OperatorValue = helperVisualQueryObject.OperatorValue;


            if (visualQueryData.LabelType == "column")
            {

                ColumnDescriptionObject descriptionValue = visualQueryData.ColumnDiscriptor;
                Label droppedElement = new Label();

                Binding binding = new Binding();
                binding.Source = visualQueryData;
                binding.Path = new PropertyPath("ColumnDiscriptor");
                binding.Mode = BindingMode.TwoWay;
                droppedElement.SetBinding(Label.DataContextProperty, binding);

                droppedElement.Content = visualQueryData.ColumnDiscriptor.TableName + "." + visualQueryData.ColumnDiscriptor.ColumnName;


                droppedElement.Foreground = Brushes.White;
                droppedElement.Background = Brushes.DarkOrange;

                droppedElement.BorderThickness = new Thickness(5);

                droppedLabel.MouseDoubleClick += columnLabel_MouseDown;
                ViewUIElements.Add(droppedElement);

            }
            else if (visualQueryData.LabelType == "controller")
            {

                Label droppedElement = new Label();

                Binding binding = new Binding();
                binding.Source = visualQueryData;
                binding.Path = new PropertyPath("OperatorValue");
                binding.Mode = BindingMode.TwoWay;
                droppedElement.SetBinding(Label.DataContextProperty, binding);


                droppedElement.Content = draggedContent.OperatorValue;
                droppedElement.Foreground = Brushes.White;
                droppedElement.Background = Brushes.Crimson;
                droppedElement.BorderThickness = new Thickness(5);

                droppedElement.MouseDoubleClick += columnLabel_MouseDown;

                ViewUIElements.Add(new Label());

            }
            else if (visualQueryData.LabelType == "value")
            {
                TextBox droppedElement = new TextBox();

                Binding binding = new Binding();
                binding.Source = visualQueryData;
                binding.Path = new PropertyPath("ComparedValue");
                binding.Mode = BindingMode.TwoWay;
                droppedElement.SetBinding(TextBox.TextProperty, binding);

               droppedElement.MouseDoubleClick += columnLabel_MouseDown;

                ViewUIElements.Add(droppedElement);
            }

            QueryDesignerModel.QueryDesignHelperCollection.Add(visualQueryData);

    }

どんな助けでも深く感謝します!

4

2 に答える 2

3

UIElements約束通り、内部がない例を作成しましたViewModels

まず、メソッドから多くのコードを削除しました。

public class MainViewModel
{
    public MainViewModel()
    {
        //For demonstration
        this.ViewUIElements = new ObservableCollection<VisualQueryObject>
        {
            new VisualQueryObject{LabelType = "column", ColumnDiscriptor = new DescriptionModel("Table1", "Column2") },
            new VisualQueryObject{LabelType = "controller"},
            new VisualQueryObject{LabelType = "value"},
        };
    }

    public void UpdateCollection(VisualQueryObject helperVisualQueryObject)
    {
        VisualQueryObject visualQueryData = new VisualQueryObject();
        //I would remove copying, but maybe it is intended behavior
        //***Taking a copy of the static DraggedData object to be bound           
        visualQueryData.ColumnDiscriptor = helperVisualQueryObject.ColumnDiscriptor;
        visualQueryData.ComparedValue = helperVisualQueryObject.ComparedValue;
        visualQueryData.JoinWithColumnDescriptor = helperVisualQueryObject.JoinWithColumnDescriptor;
        visualQueryData.LabelType = helperVisualQueryObject.LabelType;
        visualQueryData.OperatorValue = helperVisualQueryObject.OperatorValue;

        this.ViewUIElements.Add(visualQueryData);

        //QueryDesignerModel.QueryDesignHelperCollection.Add(visualQueryData);   //I don't know what this method does
    }

    public ObservableCollection<VisualQueryObject> ViewUIElements { get; private set; }
}

次にDataTemplateSelector、質問の関数からif句を配置したクラスを作成しました。

public class QueryObjectDateTemplateSelector : DataTemplateSelector
{
    public DataTemplate ColumnTemplate { get; set; }

    public DataTemplate ControllerTemplate { get; set; }

    public DataTemplate ValueTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
    {
        var visualQueryData = item as VisualQueryObject;
        if (visualQueryData == null)
            return null;

        if (visualQueryData.LabelType == "column")
            return ColumnTemplate;
        else if (visualQueryData.LabelType == "controller")
            return ControllerTemplate;
        else if (visualQueryData.LabelType == "value")
            return ValueTemplate;
        else return null;

    }
}

そして、それはほとんどすべてです。他のすべてが入っていxamlます:

<Window.Resources>
    <ItemsPanelTemplate x:Key="WrapPanelTemplate">
        <WrapPanel Orientation="Horizontal" />
    </ItemsPanelTemplate>

    <DataTemplate x:Key="ColumnDataTemplate">
        <Label DataContext="{Binding ColumnDiscriptor}" Foreground="White" Background="DarkOrange" BorderThickness="5">
            <TextBlock>
                <Run Text="{Binding TableName}"/><Run Text="."/><Run Text="{Binding ColumnName}"/> 
            </TextBlock>
        </Label>
    </DataTemplate>
    <DataTemplate x:Key="ControllerDataTemplate">
        <Label Content="Controller"/>
    </DataTemplate>
    <DataTemplate x:Key="ValueDataTemplate">
        <TextBox Text="Value"/>
    </DataTemplate>
    <local:QueryObjectDateTemplateSelector x:Key="ModelSelector"
                                           ColumnTemplate="{StaticResource ColumnDataTemplate}"
                                           ControllerTemplate="{StaticResource ControllerDataTemplate}"
                                           ValueTemplate="{StaticResource ValueDataTemplate}"/>
</Window.Resources>
<Window.DataContext>
    <local:MainViewModel/>
</Window.DataContext>

<Grid>
    <ItemsControl ItemsSource="{Binding ViewUIElements}" ItemsPanel="{StaticResource WrapPanelTemplate}" 
                  ItemTemplateSelector="{StaticResource ModelSelector}"/>
</Grid>

列テンプレートのみをコーディングしました。他のテンプレートもxamlで書き直す必要があります。これで、このメソッドを呼び出すことができます。

((MainViewModel)this.DataContext).UpdateCollection(DraggedData as VisualQueryObject);
于 2011-03-25T19:24:17.467 に答える
1

何を求めているのかよくわかりませんが、データテンプレートを使用しItemTemplateて、ListBox基になるバインドされたデータオブジェクトタイプに基づいてのを変更したいようです。

したがって、あなたの場合ObservableCollection<LabelType>、ラベルタイプがラベルタイプ(列、コントローラー、値)ごとに派生タイプを持っている場合は、暗黙のデータテンプレート(DataTypeプロパティを使用)を使用して、サブタイプごとに適切なテンプレートを選択できます。

LabelTypeまたは、オブジェクトのタイプを列挙したものを使用することもできます。

ObservableCollection<LabelType> Labels ...

Labels.Add(new ControllerLabelType());

...

<ListBox ItemsSource="{Binding Labels}">
  <ListBox.Resources>
    <DataTemplate DataType="{x:Type local:ControllerLabelType}">
      <TextBlock Text="{Binding OperatorValue}" />
    </DataTemplate>
    <DataTemplate DataType="{x:Type local:ValueLabelType}">
      <TextBox Text="{Binding OperatorValue}" />
    </DataTemplate>        
  </ListBox.Resources>
  <ListBox.ItemsPanel>
    <ItemsPanelTemplate>
      <WrapPanel IsItemsHost="True" />
    </ItemsPanelTemplate>
  </ListBox.ItemsPanel>
</ListBox>    

データテンプレートの詳細については、 http://msdn.microsoft.com/en-us/library/ms742521.aspxを参照してください。

于 2011-03-25T11:44:05.233 に答える