WPF:我如何设置我的模型和绑定策略?

时间:2010-06-19 19:45:39

标签: wpf mvvm binding combobox viewmodel

注意这张图片: alt text http://img25.imageshack.us/img25/9743/timetablepo.png

此用户界面的 TimeTableViewModel 是:

public string SchoolclassCodeMonday {get;set;}
public string SchoolclassCodeTuesday {get;set;}
public string SchoolclassCodeWednesday {get;set;}
public string SchoolclassCodeThursday {get;set;}
public string SchoolclassCodeFriday {get;set;}
public string SchoolclassCodeSaturday {get;set;}
public string SchoolclassCodeSunday {get;set;}

当我在文本框中仅显示属性作为字符串时,上述操作将起作用。 但我想要的是将每个 combox绑定到相互ObservableCollection SchoolclassCodes 和ComboBox的SelectedItem aka DisplayMember必须以某种方式 映射到上述7个属性之一,如果检索到SelectedItem,则必须提供一行 在组合框中选出的所有7个学校班级。

或者换句话说我真正想要的是什么; - )

在ComboBox中显示SchoolclassCodes列表,将 的值> SelectedItem.SchoolclassCode“WeekdayName”设置为所选的ComboboxItem.SchoolclassCode

的值

我有一些想法,但都缺乏使它们完全发挥作用的经验。

我可以为每个属性添加 TimeTableViewModel a ObservableCollection SchoolclassCodes 但这对我来说似乎非常多余。当每个单元格中包含相同项目的相同列表时,为什么我应该为一行保留7个列表?

欢迎任何有关ViewModels结构和Wpf绑定的建议:)

UPDATE :我的 SchoolclassCodes 列表是动态创建的,所以我不可能在XAML中使用静态绑定或硬编码字符串项...

UPDATE2:

好的我试着让它与MVVM一起工作:

我必须更改 ObservableCollection ClassCodes ObservableCollection SchoolclassCodes作为Schoolclass对象 有一个不可能的字符串引用Pupil类。

Schoolclass.cs:

public string SchoolclassCode {get;set;}
...

TimeTableWeekViewModel.cs:

public ObservableCollection<Schoolclass> SchoolclassCodes
    {
        get { return _schoolclassCodes; }
        set
        {
            _schoolclassCodes = value;
            this.RaisePropertyChanged("SchoolclassCodes");
        }
    }

XAML:

绑定如何看起来像NOW,因为wpf找不到SchoolclassCodes?

3 个答案:

答案 0 :(得分:1)

如果您正在执行任何远程复杂的操作,我建议您查看MVVM(Model-View-ViewModel)模式。此外,在您的模型/ viewmodel中实现INotifyPropertyChanged非常有用(例如,下面示例中的MyWeek类)。只要您的某个SchoolclassCode<Day>属性发生更改,这将通知任何其他绑定。

以下是一些简单的示例代码,可帮助您入门:

using System.Collections.ObjectModel;
using System.Linq;

namespace BindingSample
{
    public partial class Window1
    {
        public Window1()
        {
            InitializeComponent();
            SchoolclassCodes = new ObservableCollection<string>(
                Enumerable.Range(1, 10).Select(i => "Code #" + i));
            MyWeeks = new ObservableCollection<MyWeek>(
                Enumerable.Range(1, 5).Select(i => new MyWeek() {SchoolclassCodeMonday = SchoolclassCodes.First()}));
            DataContext = this;
        }

        public ObservableCollection<string> SchoolclassCodes { get; private set; }
        public ObservableCollection<MyWeek> MyWeeks { get; private set; }
    }

    public class MyWeek
    {
        public string SchoolclassCodeMonday { get; set; }
        public string SchoolclassCodeTuesday { get; set; }
        public string SchoolclassCodeWednesday { get; set; }
        public string SchoolclassCodeThursday { get; set; }
        public string SchoolclassCodeFriday { get; set; }
        public string SchoolclassCodeSaturday { get; set; }
        public string SchoolclassCodeSunday { get; set; }
    }
}

<Window x:Class="BindingSample.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <CollectionViewSource x:Key="ClassCodes" Source="{Binding SchoolclassCodes}" />
    </Window.Resources>
    <ListView ItemsSource="{Binding MyWeeks}">
        <ListView.View>
            <GridView>
                <GridView.Columns>
                    <GridViewColumn Header="Monday">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <ComboBox SelectedValue="{Binding SchoolclassCodeMonday}"
                                          ItemsSource="{Binding Source={StaticResource ClassCodes}}"
                                          IsSynchronizedWithCurrentItem="False" />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <!-- Other columns here... -->
                </GridView.Columns>
            </GridView>
        </ListView.View>
    </ListView>
</Window>

答案 1 :(得分:0)

由于必须自动生成列,因此将此代码放在适当的位置(Loaded event?)应该可以执行您想要的操作:

        ObservableCollection<String> Collection = GetCollection();

        foreach (DataGridComboBoxColumn column in DataGrid1.Columns.OfType<DataGridComboBoxColumn>())
        {
            column.ItemsSource = Collection;
        }

当然,必须进行一些修改!

答案 2 :(得分:0)

您不需要乱用DataGrid,并且您当然不需要创建任何具有七个不同属性的类,您必须为其实现属性更改通知。 Grid控件使日历变得简单。

您的视图模型应包含三个类:MonthWeekDayWeek类包含Day个对象的列表,Month类包含Week个对象的列表。每个类都应该引用其父级,即Week中的DayMonth中的Week

Week类的构造函数应将其Days属性初始化为7 Day个对象的列表。 Month类的构造函数必须具有更具体的逻辑来设置其Weeks属性;我会留给你的。

Day对象应该公开这些属性:

public DayOfWeek DayNumber { get; private set; }
public ObservableCollection<SchoolclassCode> Codes { get { return Week.Codes; } }

以及执行属性更改通知的读/写字符串Code属性。

Week对象应该公开:

public ObservableCollection<SchoolclassCode> Codes { get { return Month.Codes; } }
public IEnumerable<Day> Days { get; private set; }
public IEnumerable<string> Codes
{
   get { return Days.Select(x => x.Code); }
}

然后,您可以定义用于呈现日期的数据模板:

<DataTemplate DataType="{x:Type local:Day}">
   <Grid>
      <Grid.ColumnDefinitions>
         <ColumnDefinition SharedSizeGroup="Sunday"/>
         <ColumnDefinition SharedSizeGroup="Monday"/>
         <ColumnDefinition SharedSizeGroup="Tuesday"/>
         <ColumnDefinition SharedSizeGroup="Wednesday"/>
         <ColumnDefinition SharedSizeGroup="Thursday"/>
         <ColumnDefinition SharedSizeGroup="Friday"/>
         <ColumnDefinition SharedSizeGroup="Saturday"/>
      </Grid.ColumnDefinitions>
      <ComboBox 
         Grid.Column="{Binding DayNumber}" 
         ItemsSource="{Binding Codes}" 
         SelectedValue="{Binding Code, Mode=TwoWay}"/>
   </Grid>
</DataTemplate>

和周:

<DataTemplate DataType="{x:Type Week}">
  <ItemsControl ItemsSource="{Binding Days}">
    <ItemsControl.ItemTemplate>
      <ItemsPanelTemplate>
        <StackPanel Orientation="Horizontal"/>
      </ItemsPanelTemplate>
    </ItemsControl.ItemTemplate>
  </ItemsControl>
</DataTemplate>

和月:

<DataTemplate DataType="{x:Type Month}">
  <ItemsControl ItemsSource="{Binding Weeks}" Grid.IsSharedSizeScope="True">
    <ItemsControl.ItemTemplate>
      <ItemsPanelTemplate>
        <StackPanel Orientation="Vertical"/>
      </ItemsPanelTemplate>
    </ItemsControl.ItemTemplate>
  </ItemsControl>
</DataTemplate>

将上述日期名称和周数添加到上述模板中非常简单。