c# - 数据网格绑定(bind) MVVM

标签 c# wpf xaml mvvm datagrid

我对 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();
    }
}

我想在我的 View 上显示一个数据网格,它将通过继承自 ObservableObject 的 ToDoListModelView 绑定(bind)到 ToDoListModel。 ObservableObject 实现 INotifyPropertyChanged
public class ToDoListModelView:ObservableObject
{
    ToDoListModel _myModel = new ToDoListModel();
    ...
}

我的 View 由下面的 xaml 代码定义: 基本上,我想将该数据网格绑定(bind)到我的 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 后,程序运行了,但我没有看到绑定(bind)到数据的内容,尽管我确实在列表中至少有 1 个项目。我做错了什么?我知道它远未完成,但至少,我应该在数据网格的列表中看到 ToDoItem?我错过了什么?
请帮忙。谢谢!

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

ToDoListModel 从 List 继承,具有返回基础数据的属性 ToDoList
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"));
    }

为了简单和说明起见,我还更正了数据网格以绑定(bind)到 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>

最佳答案

你设置你的DataContext属性到没有名为“ToDoListModelView”的属性的“模型”类(您永远不应该做的事情,始终设置为 ViewModel 类),因此绑定(bind)失败(您应该将其视为 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 属性(尽管有时需要)。然后我绑定(bind)到一个可能是 ToDoListModel 的实例的(虚构的)属性。 .

其他一些旁白:
  • 如果您正在继承 IList你可能做错了! ObservableCollection 有什么问题|或其他现有实现之一?
  • 它的“ViewModel”不是“ModelView”,只是作为命名约定

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

    关于c# - 数据网格绑定(bind) MVVM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23769653/

    相关文章:

    C# 2010 Microsoft Chart 4.0 控件没有 ChartType 属性?

    c# - 通用项目的 WPF 转换

    c# - wpf MvvM 命令数据上下文问题

    c# - 更新元素时​​的 WPF 性能

    c# - MongoDB 驱动程序 2.2 的动态类型 - 如何不序列化 _t 类型鉴别器?

    c# - 禁用/隐藏脚本管理器

    wpf - F# wpf 异步命令完成状态

    WPF 交互在样式中触发以调用 View 模型上的命令

    c# - 列表框.SelectedItem

    c# - 在 XSL 中使用特殊字符