【问题标题】:Datagrid binding MVVM数据网格绑定 MVVM
【发布时间】:2014-05-20 20:47:40
【问题描述】:

我对 MVVM 非常陌生,我只是想通过一个小型测试 wpf 应用程序来弄湿我的脚。我有一个模型调用 ToDoItemModel 定义如下:(基本上我有一个名为 ToDoItemModel 和 ToDoItemListModel 的类,它实现了 IList

public class ToDoItemModel
{
    private DateTime    _TodoDate;
    private string      _TodoDescription;
    private TimeSpan    _TodoTimeSpan;
    private string      _StartTime;

    public ToDoItemModel(DateTime d, string s)
    {
        _TodoDate=d;
        _TodoDescription=s;
    }

    public string StartTime
    {
        get { return      _StartTime; }
        set {      _StartTime = value; }
    }


    public TimeSpan ToDoTimeSpan
    {
        get { return _TodoTimeSpan; }
        set { _TodoTimeSpan = value; }
    }

    public string ToDoDescription
    {
        get { return _TodoDescription; }
        set { _TodoDescription = value; }
    }

    public DateTime ToDoDate
    {
        get { return _TodoDate; }
        set { _TodoDate = value; }
    }

    public override string ToString()
    {
        return string.Format("Date: {0}- Time: {1}- Duration: {2}- Description: {3}",_TodoDate.ToString("d"),_StartTime,_TodoTimeSpan,_TodoDescription);
    }       
}

public class ToDoListModel: IList<ToDoItemModel>
{
    private readonly IList<ToDoItemModel> _todoList = new List<ToDoItemModel>();

    public ToDoListModel()
    {
         //Hard code this one for testing purpose
        _todoList.Add(new ToDoItemModel(DateTime.Now,"Testing"));
    }

    public int IndexOf(ToDoItemModel item)
    {
        return _todoList.IndexOf(item);
    }

    public void Insert(int index, ToDoItemModel item)
    {
        _todoList.Insert(index,item);
    }

    public void RemoveAt(int index)
    {
        _todoList.RemoveAt(index);
    }

    public ToDoItemModel this[int index]
    {
        get
        {
            return _todoList[index];
        }
        set
        {
            _todoList[index]=value;
        }
    }

    public void Add(ToDoItemModel item)
    {
        _todoList.Add(item);
    }

    public void Clear()
    {
        _todoList.Clear();
    }

    public bool Contains(ToDoItemModel item)
    {
        return _todoList.Contains(item);
    }

    public void CopyTo(ToDoItemModel[] array, int arrayIndex)
    {
        _todoList.CopyTo(array,arrayIndex);
    }

    public int Count
    {
        get { return _todoList.Count; }
    }

    public bool IsReadOnly
    {
        get { return _todoList.IsReadOnly; }
    }

    public bool Remove(ToDoItemModel item)
    {
        return _todoList.Remove(item);
    }

    public IEnumerator<ToDoItemModel> GetEnumerator()
    {
        return _todoList.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

我想在我的视图上显示一个数据网格,它将通过继承自 ObservableObject 的 ToDoListModelView 绑定到 ToDoListModel。 ObservableObject 实现 INotifyPropertyChanged

public class ToDoListModelView:ObservableObject
{
    ToDoListModel _myModel = new ToDoListModel();
    ...
}

我的视图由下面的 xaml 代码定义:基本上,我想将该数据网格绑定到我的 ToDoListModel。

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TestWPF" x:Class="TestWPF.MainWindow"
        Title="MainWindow" Height="350" Width="525">
    <Grid Margin="1,0,-1,0">
        <DataGrid x:Name="ExistingToDoList" 
          HorizontalAlignment="Left" 
          Margin="33,201,0,0" 
          VerticalAlignment="Top" 
          Height="94" Width="464" 
          Background="#FFF1E6E6" 
          GridLinesVisibility="Horizontal" 
          ItemsSource="{Binding ToDoListModelView}" 
          Style="{DynamicResource ToDoEntry}">
            <DataGrid.DataContext>
                <local:ToDoListModel/>
            </DataGrid.DataContext>
        </DataGrid>
    </Grid>
</Window>

但是,在按 F5 后,程序运行了,但我没有看到绑定到数据的内容,尽管我确实在列表中至少有 1 个项目。我做错了什么?我知道它远未完成,但至少,我应该在数据网格的列表中看到 ToDoItem?我错过了什么? 请帮忙。谢谢!

---- 我的更新 ----------------------------------------- -----

ToDoListModel 继承自具有返回基础数据的属性 ToDoList 的 List

public class ToDoListModel: List<ToDoItemModel>
{
    private  List<ToDoItemModel> _todoList = new List<ToDoItemModel>();
    public List<ToDoItemModel> TodoList
    {
        get { return _todoList; }
    }

    public ToDoListModel()
    {
        _todoList.Add(new ToDoItemModel(DateTime.Now,"Testing"));
    }

为了简单起见,我还更正了数据网格以绑定到 ToDoList 并将 autoGeneratecolumn 设置为 true。

<Grid Margin="1,0,-1,0" d:DataContext="{d:DesignData /SampleData/ToDoListModelSampleData.xaml}">
    <DataGrid x:Name="ExistingToDoList" 
        HorizontalAlignment="Left" 
        Margin="33,201,0,0" 
        VerticalAlignment="Top" 
        Height="94" Width="464" 
        Background="#FFF1E6E6" 
        GridLinesVisibility="Horizontal" 
        ItemsSource="{Binding TodoList}" 
        Style="{DynamicResource ToDoEntry}" 
        AutoGenerateColumns="True"
        DataContext="{Binding Mode=OneWay}">
        <DataGrid.ItemBindingGroup>
            <BindingGroup/>
        </DataGrid.ItemBindingGroup>
    </DataGrid>

【问题讨论】:

  • 根据您提供的内容,您似乎没有将网格绑定到 IEnumerable,而是绑定到包含 IEnumerable 的类。

标签: c# wpf xaml mvvm datagrid


【解决方案1】:

您将DataContext 属性设置为“模型”类(您永远不应该这样做,始终设置为 ViewModel 类),它没有名为“ToDoListModelView”的属性,因此绑定失败(您应该看到这作为输出窗口中的 System.Data 异常)。

ItemsSource="{Binding ToDoListModelView}" 说“在我的 DataContext 上查找一个名为 'ToDoListModelView' 的属性并将其用作我的 ItemsSource”。你可能打算做的是:

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TestWPF" x:Class="TestWPF.MainWindow"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
       <local:ToDoListModelView/>
    </Window.DataContext>
    <Grid Margin="1,0,-1,0">
        <DataGrid x:Name="ExistingToDoList" 
          ItemsSource="{Binding MyModelProperty}" 
        </DataGrid>
    </Grid>
</Window>

请注意,我将 DataContext 设置为 ViewModel 对象(不是模型),并将其设置为窗口。这纯粹是风格,但您通常不设置特定控件的 DataContext 属性(尽管有时需要)。然后我绑定到一个可能是ToDoListModel 实例的(虚构的)属性。

其他一些旁白:

  1. 如果您继承IList,您可能做错了! ObservableCollection 或其他现有实现之一有什么问题?
  2. 它的“ViewModel”不是“ModelView”,只是命名约定

类似,但不重复(答案可以帮助您:Setting DataContext in XAML in WPF

【讨论】:

  • 感谢您指出我的代码中的问题区域。对于这种情况,ILIST 绝对是矫枉过正。我已将其更改为 LIST 和命名约定。我对此完全是绿色的。我仍然有点模糊的是 ItemsSource 绑定:应该将它绑定到一行还是整个类?假设我用一个返回整个 List 的属性 ToDoList 和一个属性说 ToDoListAt(index) 更改我的类 ToDoListModel: List。当我绑定 itemsource 时,我应该将它绑定到 ToDoList 还是 ToDoListAt?我必须在数据网格中定义每个字段吗?
  • 您绑定到“ToDoList”(ItemsSource 始终绑定到一个集合),是的,您需要定义每个字段(AutoGenerateColumns 可以工作,但您几乎总是希望它自定义)。这有意义吗?
  • 是的,应该。我完全理解你的解释。但是,启动应用程序时它仍然没有显示数据。它在设计时显示列,但不显示运行时。我想知道我错过了什么?为了清楚我的问题,我更新了我更改的部分
  • @user1205746 您的 DataContext 是否设置为 ToDoListModel?那仍然是关闭的,你也不应该从 List 派生。为什么没有一个只拥有一个列表的 ViewModel 类?这仍然以非常有趣的方式设置。
  • 啊!数据上下文!!!我错过了……难怪!是的,我是新手,所以我想弄湿我的脚,所以有很多事情是不合时宜的。谢谢你指出。非常感谢!
猜你喜欢
  • 2012-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-30
  • 2014-01-29
  • 1970-01-01
相关资源
最近更新 更多