开发者

WPF: How do I have to setup my model and the binding strategy?

开发者 https://www.devze.com 2023-01-03 21:10 出处:网络
Regard this image: alt text http://img25.imageshack.us/img25/9743/timetablepo.png The TimeTableViewModel of this user interface is this:

Regard this image: alt text http://img25.imageshack.us/img25/9743/timetablepo.png

The TimeTableViewModel of this user interface is this:

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;}

The above would work when I would display only the properties as string in a textbox. But what I want is to bind each combox to a mutual ObservableCollection SchoolclassCodes and the SelectedItem aka DisplayMember of the ComboBox must somehow be MAPPED to one of the 7 above Properties AND the SelectedItem if retrieved must supply a row of all 7 schoolclass selected in the combobox.

Or what I actually want just in other words ;-)

Display in the ComboBox the SchoolclassCodes list, set the Value of SelectedItem.SchoolclassCode"WeekdayName" to the Value of the selected ComboboxItem.SchoolclassCode

Well there are some ideas I have but all lack some experience to make them fully working.

I could add to the TimeTableViewModel for each Property a ObservableCollection SchoolclassCodes but that seems very redundant to me. Why should I hold 7 lists for ONE row when each cell has the same list with the same items in it ?

Any suggestions concerning the ViewModels structure and the binding in Wpf are welcome :)

UPDATE: My SchoolclassCodes list is dynamically created, so I there is no possibility about static binding or hardcode string items in XAML...

UPDATE2:

OK I tried to m开发者_如何学Pythonake it working with MVVM:

I had to change the ObservableCollection ClassCodes to ObservableCollection SchoolclassCodes as the Schoolclass object has a reference to Pupil class with strings thats not possible.

Schoolclass.cs:

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

TimeTableWeekViewModel.cs:

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

XAML:

How must the binding look like NOW because the SchoolclassCodes is not found by wpf ?


I recommend that you look into the MVVM (Model-View-ViewModel) pattern if you are doing anything remotely complicated. Also, it is useful to implement INotifyPropertyChanged in your model/viewmodel (e.g. the MyWeek class in my example below). That will notify any other bindings whenever one of your SchoolclassCode<Day> properties is changed.

Here is some simple sample code to get you started:

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>


Since the columns must be auto generated, putting this code in the appropriate place (Loaded event?) should do what you want :

        ObservableCollection<String> Collection = GetCollection();

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

Of course, some modifications must be applied!


You don't need to mess around with the DataGrid, and you certainly don't need to create any class with seven different properties that you have to implement property-change notification for. The Grid control makes calendars easy.

Your view model should have three classes: Month, Week, and Day. The Week class contains a list of Day objects, and the Month class has a list of Week objects. Each class should have a reference to its parent, i.e. Week in Day and Month in Week.

The Week class's constructor should initialize its Days property to be a list of 7 Day objects. The Month class's constructor has to have more specific logic in it for setting up its Weeks property; I'll leave that to you.

The Day object should expose these properties:

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

as well as a read/write string Code property that does property-change notification.

The Week object should expose:

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); }
}

You can then define a data template for presenting days:

<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>

and weeks:

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

and months:

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

Adding day names and week numbers to the above templates is straightforward.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号