父窗口中的数据更改反映错误

时间:2012-04-25 05:27:37

标签: c# wpf data-binding

我有以下要求:

  1. 显示项目的TreeView
  2. TreeView
  3. 中显示所选项目的详细信息
  4. 用于编辑所选项目的对话框。
  5. 我已经实现了这些要求,但是第三个要求没有按预期执行,所以我被卡住了。

    我想要它做什么: 编辑对话框应该能够编辑项目。这不是TreeViewItem,而是我的一个类的实例。

    1. 保存编辑 - 一个只关闭对话框的按钮。
    2. 放弃编辑 - 用于重置项目和关闭对话框中更改的字段的按钮。
    3. 第二项要求不起作用。如果我编辑字段并点击取消,则项目详细信息面板仍会显示编辑内容。我已经调试但是我发现基础项目没有改变 - 但是项目显示的是更改的值。

      代码:

      1. 项目类别(类别)

        public class Category
        {
            public virtual int Id { get; set; }
            public virtual string Name { get; set; }
            public virtual string Description { get; set; }
            public virtual Unit Unit { get; set; }
            public virtual List<Category> ChildCategories { get; set; }
            public virtual Category ParentCategory { get; set; }
            public virtual bool IsMainCategory { get; set; }
        
            public Category()
            {
                ChildCategories = new List<Category>();
            }
        
            public virtual void AddChild(Category child)
            {
                ChildCategories.Add(child);
                child.ParentCategory = this;
            }
        }
        
      2. 项目(类别)详细信息显示在标签中:

        <DataTemplate DataType="{x:Type local:Category}">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="4*" SharedSizeGroup="a" />
                    <ColumnDefinition Width="6*" SharedSizeGroup="b" />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="1*" />
                    <RowDefinition Height="1*" />
                </Grid.RowDefinitions>
        
                <TextBlock Text="Name" Grid.Column="0" Grid.Row="0" Padding="5"/>
                <TextBlock Text="{Binding Path=Name}" Grid.Column="1" Grid.Row="0" Padding="5"/>
                <TextBlock Text="Description" Grid.Column="0" Grid.Row="1" Padding="5"/>
                <TextBlock Text="{Binding Path=Description}" Grid.Column="1" Grid.Row="1" Padding="5"/>
            </Grid>
        </DataTemplate>
        
      3. 主窗口中编辑项目的事件处理程序:

        private void EditCategory(object sender, RoutedEventArgs e)
        {
            Category ctg = _tree.SelectedItem as Category;
            if (ctg != null)
            {
                CategoryDefineWindow cdw = new CategoryDefineWindow();
                cdw.CategoryObject = ctg;
                cdw.ShowDialog();
            }
        }
        
      4. 项目编辑器窗口xaml:

        <Window x:Class="BSRCat.View.CategoryDefineWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Height="150" Width="500">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="3*" SharedSizeGroup="a" />
                <ColumnDefinition Width="7*" SharedSizeGroup="b" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
            </Grid.RowDefinitions>
        
            <TextBlock Text="Name" Grid.Column="0" Grid.Row="0" Padding="5"/>
            <TextBox Text="{Binding Path=CategoryObject.Name, RelativeSource={RelativeSource AncestorType=Window}}" Grid.Column="1" Grid.Row="0" Padding="5"/>
            <TextBlock Text="Description" Grid.Column="0" Grid.Row="1" Padding="5"/>
            <TextBox Text="{Binding Path=CategoryObject.Description, RelativeSource={RelativeSource AncestorType=Window}}" Grid.Column="1" Grid.Row="1" Padding="5"/>
        
            <StackPanel Orientation="Horizontal" Grid.Row="2" Grid.ColumnSpan="2" HorizontalAlignment="Right">
                <Button Content="Ok" Margin="5" Height="20" Width="30" Click="Confirmed"/>
                <Button Content="Cancel" Margin="5" Height="20" Width="50" Click="Cancelled"/>
            </StackPanel>
        </Grid>
        </Window>
        
      5. 项目编辑器窗口代码背后:

        public partial class CategoryDefineWindow : Window
        {
            public Category CategoryObject 
            {
                get
                {
                return _category;
                }
                set
                {
                    _category = value;
                    _initial = new Category() { Name = value.Name, Description = value.Description     };
                }
            }
        
            private Category _category;
            private Category _initial;
        
            public CategoryDefineWindow()
            {
                InitializeComponent();
            }
        
            private void Confirmed(object sender, RoutedEventArgs e)
            {
                Close();
            }
        
            private void Cancelled(object sender, RoutedEventArgs e)
            {
                _category.Name = _initial.Name;
                _category.Description = _initial.Description;
                Close();
            }
        }
        
      6. 我调试了CategoryDefineWindow.Cancelled方法,并且正确重置了_category对象。我找不到它出错的地方。

1 个答案:

答案 0 :(得分:1)

类别类应该实现INotifyPropertyChanged接口。一旦属性值发生变化,WPF将会收到通知。

   public class Category : INotifyPropertyChanged
{
    private string _Name;
    private string _Description;

    public virtual int Id { get; set; }
    public virtual string Name
    {
        get
        {
            return _Name;
        }
        set
        {
            if (_Name == value)
                return;

            _Name = value;
            NotifyPropertyChanged("Name");
        }
    }

    public virtual string Description
    {
        get
        {
            return _Description;
        }
        set
        {
            if (_Description == value)
                return;

            _Description = value;
            NotifyPropertyChanged("Description");
        }
    }
    public virtual Unit Unit { get; set; }
    public virtual List<Category> ChildCategories { get; set; }
    public virtual Category ParentCategory { get; set; }
    public virtual bool IsMainCategory { get; set; }

    public Category()
    {
        ChildCategories = new List<Category>();
    }

    public virtual void AddChild(Category child)
    {
        ChildCategories.Add(child);
        child.ParentCategory = this;
    }

    private void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}