mvvm中的DataBinding问题

时间:2010-06-30 20:15:35

标签: c# wpf mvvm

我的数据绑定存在很大问题。 我无法将数据绑定到子控件。我是MVVM的新手,我在这个例子上花了很多时间,我不知道这个代码有什么问题。

小解释:

我有MainWindow。它有UserControl来显示待办事项列表。 我想将MyWindow类ParentViewModel设置为DataContext。 DataContext将TodoItemModelView作为subatacontext,它必须是UserControlTodoItems的datacontext。

<Window x:Class="Repo.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Repo="clr-namespace:Repo" Title="Window1" Height="300" Width="300">
    <Window.Resources>

        <Repo:ParentViewModel x:Key="parentVM"/>

    </Window.Resources>

    <Window.DataContext>
        <StaticResourceExtension ResourceKey="parentVM"/>
    </Window.DataContext>
    <Grid>
           <Repo:UserControlTodoItems DataContext="{Binding Path=todoItemModelView}">

           </Repo:UserControlTodoItems>
                      </Grid>
</Window>

public partial class MainWindow : Window
{

    public MainWindow()
    {
        InitializeComponent();
     }



 class ParentViewModel
        {
            public TodoItemModelView todoItemModelView { get; set; } 
            public ParentViewModel()
            {
               this.todoItemModelView=new TodoItemModelView();
            }
        }


public class TodoItemModelView
{
    public ObservableCollection<TodoItem> todoItems { get; set; }

    public TodoItemModelView()
    {
        ObservableCollection<TodoItem> loadedTodoItems = new ObservableCollection<TodoItem>();
        loadedTodoItems.Add(new TodoItem() { Code = "10", ObjectCode = "DE", ObjectType = ObjectType.Country, Status = TodoItemStatus.InProgress, Type = TodoItemType.CollectPhotos });
        loadedTodoItems.Add(new TodoItem() { Code = "11", ObjectCode = "DE", ObjectType = ObjectType.Country, Status = TodoItemStatus.Todo, Type = TodoItemType.DescribeOjbect });
        loadedTodoItems.Add(new TodoItem() { Code = "12", ObjectCode = "DE", ObjectType = ObjectType.Country, Status = TodoItemStatus.Accomplshed, Type = TodoItemType.CollectVideos });
        todoItems = loadedTodoItems;
    }
}

<UserControl x:Class="Repo.UserControlTodoItems"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Repo="clr-namespace:Repo" Height="auto" Width="auto">
    <UserControl.Resources>
        <Repo:TodoItemStatusConverter x:Key="TodoItemStatusConverter"/>

    </UserControl.Resources>
    <Grid>
        <ListBox ItemsSource="{Binding Path=todoItems}" Name="lbTasks"> 
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <CheckBox IsChecked="{Binding Path=Status, Converter={StaticResource TodoItemStatusConverter}}"/>
                        <TextBlock Text="{Binding Path=Type}" />
            </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

    </Grid>
</UserControl>


public UserControlTodoItems()
        {
            InitializeComponent();

        }

我纠正了这个。

我必须添加一个问题: 是否有任何简单的方法来通知parentmodel,列表框中的更改复选框?

这是一个转换器:

public class TodoItemStatusConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {

            TodoItemStatus todoItemStatus = (TodoItemStatus)value;


            if (todoItemStatus == TodoItemStatus.Accomplshed)
            {
                return true;
            }
            else
            {
                return false;
            }



        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
           if ((bool) value)
            {
                return TodoItemStatus.Accomplshed;
            }
            else
            {
                return TodoItemStatus.InProgress;
            }

        }

这是TodoItem类:

public class TodoItem
    {
        public TodoItemType Type { get; set; }

        public TodoItemStatus Status { get; set; }

        public string Code { get; set; }

        public string ObjectCode { get; set; }

        public ObjectType ObjectType { get; set; }
    }

2 个答案:

答案 0 :(得分:1)

为什么“lbTasks”列表框的绑定只是“{Binding}”而不是“{Binding Path = todoItems}”

我真的在这里快速浏览一下你的代码..你似乎正确地将todoItemModelView作为DataContext传递,但是从不通知列表框在该数据上下文中它将找到它的项目。

您可能还希望对VM中的列表使用ObservableCollection,以便以GUI可以响应的方式添加和删除todo

答案 1 :(得分:1)

<CheckBox IsChecked="{Binding Path=Status, Converter={StaticResource TodoItemStatusConverter}}"/>

这意味着ToDoItemViewModel上有一个名为Status的属性 - 但是没有!重新思考你的ToDoItemVm类只是一个toDoItem的包装器(即,公共ToDoItemVm(ToDoItem模型),并将该项目数组放入PArentVm(使用ObservableCollection并将其绑定到列表框。在ParentVm上添加一个SelectedToDoItem属性。因此,对列表框的绑定包括类似

的内容
          ItemsSource="{Binding ToDoTems}" 
          IsSynchronizedWithCurrentItem="True"
          SelectedItem="{Binding SelectedToDoItem, Mode=TwoWay}"

然后在ToDoItemVm上公开Status属性,让类实现INPC,并在setter中引发PropertyChanged。

可能需要一些工作来解决它,所以随时随地提出更多问题。转换器的想法很好。

HTH,
Berryl