0

我是 WPF 新手,开始学习 MVVM 概念。

我正在开发一个创建图形对象的应用程序,该对象包含来自数据库的数据。

我有一个包含多个标签和组合框的组合框。

每个人都应该持有一个来自我的数据库的列表。

对于第一个组合框,我设法使用 MVVVM 为该特定列表填充它。

但是,如果我已经使用第一个列表启动 DataContext,我该如何填充其他组合框?

我应该为每个 ComboBox 创建一个 ModelView 吗?

一般来说,我怎样才能将几个组合框动态绑定到列表?

<Label Grid.Row="0"
       Grid.Column="0"
       Grid.ColumnSpan="2"
       Name="lblTiNam">Test Item Name :</Label>
<TextBox Grid.Row="0"
         Grid.Column="2"
         Name="tbTiName"
         MinWidth="100"
         MaxWidth="100"></TextBox>
<Label Grid.Row="1"
       Grid.Column="0"
       Grid.ColumnSpan="2"
       Name="lblTiExStat">Execution Status :</Label>
<ComboBox Grid.Row="1"
          Grid.Column="2"
          x:Name="cbTiExStat"
          MinWidth="100"
          MaxWidth="100"
          SelectedValuePath="Content"
          ItemsSource="{Binding Binding QcLists.FieldList}"
          DisplayMemberPath="Name">

</ComboBox>
<Label Grid.Row="2"
       Grid.Column="0"
       Grid.ColumnSpan="2"
       Name="lblTiVersion">Version :</Label>
<ComboBox Grid.Row="2"
          Grid.Column="2"
          Name="cbTiVersion"
          MinWidth="100"
          MaxWidth="100"
          SelectedValuePath="Content"
          SelectedIndex="1">
  <ComboBoxItem>To BE Bind From QC</ComboBoxItem>
</ComboBox>
<Label Grid.Row="3"
       Grid.Column="0"
       Grid.ColumnSpan="2"
       Name="lblTiCRID">CRID :</Label>
<ComboBox Grid.Row="3"
          Grid.Column="2"
          Name="cbTiCRID"
          MinWidth="100"
          MaxWidth="100"
          SelectedValuePath="Content">
  <ComboBoxItem>To BE Bind From QC</ComboBoxItem>
</ComboBox>
<Label Grid.Row="4"
       Grid.Column="0"
       Grid.ColumnSpan="2"
       Name="lblTiApplication">Application :</Label>
<ComboBox Grid.Row="4"
          Grid.Column="2"
          Name="cbTiApplication"
          MinWidth="100"
          MaxWidth="100"
          SelectedValuePath="Content">
  <ComboBoxItem>To BE Bind From QC</ComboBoxItem>
</ComboBox>
<Label Grid.Row="5"
       Grid.Column="0"
       Grid.ColumnSpan="2"
       Name="lblTiTestLevel">Test Level :</Label>
<ComboBox Grid.Row="5"
          Grid.Column="2"
          Name="cbTiTestLevel"
          MinWidth="100"
          MaxWidth="100"
          SelectedValuePath="Content">
  <ComboBoxItem>To BE Bind From QC</ComboBoxItem>
</ComboBox>

我正在编辑我的问题以添加更多信息:

内部类 TestableItemViewModel { public QCLists QcLists { get { return _qcLists; } }

    #endregion

   #region Constructor
    public TestableItemViewModel()
    {
        _qcconnect = QCConnection.QCConnect.getInstance();
       // LoadListSettings();
        LoadListSettings( "TS_USER_05");
        SaveCommand = new TestableItemSaveDetailsCommand(this);
    }
    #endregion

    private void LoadListSettings(String FieldName)
    {
        Customization cust = QCConnection.QCConnect.getInstance().GetTD.Customization;
        CustomizationFields fields = cust.Fields;
        CustomizationListNode node;
        CustomizationField field;
        field = fields.get_Field("TEST", FieldName);
        node = field.List.RootNode;
        _qcLists = new QCLists(node.Children, node.Name);
    }

}

class QCLists:INotifyPropertyChanged
{
    TDAPIOLELib.List _fieldList;
    List<String> myTestList;
    String listName;

    public String ListName
    {
        get { return listName; }
        set { listName = value; }
    }

    public List<String> MyTestList
    {
        get { return myTestList; }
        set { myTestList = value; }
    }

    public QCLists(TDAPIOLELib.List List,String name)
    {
        _fieldList = List;
        myTestList = new List<String>();
        listName = name;
    }

    public TDAPIOLELib.List FieldList
    {
        get
        {
            return _fieldList;
        }

        set
        {
            _fieldList = value;
            OnPropertyChanged("FieldList");

        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }

    }

}

对于上面的 xaml 背后的代码:

 DataContext = new TestableItemViewModel();

这些是我使用的课程。正如您在我的 xaml 中看到的那样,第一个 combocox 绑定到所需列表,我可以看到我预期的值。我如何继续绑定其他组合框?因为我只有一个 TestableItemViewModel 实例,它已经绑定到第一个列表,并且数据上下文正在使用该列表。我还有其他需要绑定到其他控件的列表(实际上是 4 个)。当然,我使用查询来获取所需列表,但这是另一个问题,因为列表名称可以在任何给定时间更改。现在我只需要解决 5 绑定的问题。

4

4 回答 4

2

要在 MVVM 范例中绑定组合框 - 您应该向 ViewModel 类添加一个列表,并使用要在组合框中显示的项目填充它。让我用一个例子来解释:

在 ViewModel 中(应该实现接口 INotifyPropertyChanged):

public BindingList<string> Cities { get; set; } 

由于您说组合框的值是从数据库中加载的,因此您需要确保在完成加载值时在“Cities”上引发 PropertyChanged - 这样视图就知道刷新绑定到属性的任何内容“城市”。

在视图中:

<Combobox ItemsSource="{Binding Cities}" />
于 2013-10-28T14:45:04.500 回答
1

答案是,在 WPF 和 MVVM 中,我们设置DataContext单个控件的 。相反,我们有一个视图模型类的实例,它具有我们需要在 UI 中显示的所有属性,我们将设置为DataContext,UserControl或视图。

这样,所有控件都可以访问视图模型中的所有属性,因此我们只需将ItemsSource每个控件的属性设置为视图模型中的相关集合属性。

于 2013-10-28T14:41:12.027 回答
0

如果我理解正确,您想动态地将组合框添加到您的字符串中。

CS :

public class CollectionWrapper<T>  
{
    private string _title;
    public string Title
    {
        get { return _title; }
        set { _title = value; }
    }

    private IList<T> _collection;

    public IList<T> Collection
    {
        get { return _collection; }
        set { _collection = value; }
    }     

    public string DisplayMemeberPath
    {
       get;set;
    } 


}


public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
    }

    public List<string> GetNewList()
    {
        return new List<string>
        {
           "1","2","3","4","1","2","3","4","1","2","3","4","1","2","3","4"
        };
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Items.Add(new CollectionWrapper<string> { Collection = GetNewList(), Title = (Items.Count + 1 ).ToString() , DisplayMemeberPath="Content"}); 
    }

    private ObservableCollection<CollectionWrapper<string>> _items;
    public ObservableCollection<CollectionWrapper<string>> Items
    {
        get
        {
            if (_items == null)
                _items = new ObservableCollection<CollectionWrapper<string>>();
            return _items;
        }
    }
}

XAML:

 <Window.Resources>
    <DataTemplate  x:Key="listItemTemplate">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>

            <Label Content="{Binding Title}"/>
            <ComboBox Grid.Column="1" ItemsSource="{Binding Collection}" DisplayMemberPath="{Binding DisplayMemeberPath}"/>

        </Grid>            
    </DataTemplate>

</Window.Resources>

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition />
    </Grid.RowDefinitions>


    <Button Content="Add List" Click="Button_Click"/>

    <ScrollViewer Grid.Row="1">
        <ItemsControl ItemTemplate="{StaticResource listItemTemplate}" ItemsSource="{Binding Items}"/>
    </ScrollViewer>
</Grid>
于 2013-10-28T14:54:31.687 回答
0

实现这一点的一种方法是,如果您有一个用于数据库记录的模型和一个用于记录列表的模型,即

为方便起见,我将使用年份示例。

class YearModel : INotifyPropertyChanged
{
    #region Members

    myService.Year _year;

    #endregion

    #region Properties

    public myService.Year Year
    {
        get { return _year; }
    }

    public Int32 id
    {
        get { return Year.id; }
        set
        {
            Year.id = value;
            NotifyPropertyChanged("id");
        }
    }

    public String Code
    {
        get { return Year.Code; }
        set
        {
            Year.Code = value;
            NotifyPropertyChanged("Code");
        }
    }

#region Construction

    public YearModel()
    {
        this._year = new SchoolMonitor_Service.Year
        {
            id = 0,
            Code = "",
        };
    }

    #endregion
}

然后名单

class YearListModel
{
    myService.myServcieClient service = new myService.myServcieClient();

    #region Members

    private ObservableCollection<YearModel> _years;

    #endregion

    #region Properties

    public ObservableCollection<YearModel> Years
    {
        get { return _years; }
    }

    #endregion

    #region Construction

    public YearListModel()
    {
        _years = new ObservableCollection<YearModel>();

        foreach (SchoolMonitor_Service.Year y in service.GetYearList())
        {
            _years.Add(new YearModel
            {
                id = y.id,
                Code = y.Code
            }
                            );
        }
    }

    #endregion
}

然后您创建一个 ViewModel 获取您需要的所有列表,我添加了 YearGroups 作为示例:

class YearFormViewModel
{
    public YearListModel YearList { get; set; }
    public YearGroupListModel YearGroupList { get; set; }

    public YearFormViewModel()
    {
        YearList = new YearListModel;
        YearGroupList = new YearGroupListModel();
    }
}

然后您可以在窗口/页面中获取 ViewModel:

xmlns:local="clr-namespace:myProject.Models"


<Page.Resources>
    <local:YearFormViewModel x:Key="myViewModel" />
</Page.Resources>

然后相应地绑定:

<ComboBox x:Name="cbYears" 
                      DataContext="{StaticResource ResourceKey=myViewModel}"
                      ItemsSource="{Binding Path=YearList.Years}"
                      SelectedValuePath="id" 
                      DisplayMemberPath="Code"/>
<ComboBox x:Name="cbYearGroups" 
                      DataContext="{StaticResource ResourceKey=myViewModel}"
                      ItemsSource="{Binding Path=YearGroupList.YearGroups}"
                      SelectedValuePath="id" 
                      DisplayMemberPath="Code"/>
于 2013-10-28T14:58:33.337 回答