排序第二级TreeView并查看更改......可能吗?

时间:2011-07-21 05:21:49

标签: c# wpf entity-framework sorting refresh

这是我在这里的第一篇文章,我一直在尝试在其他问题中找到的一些技巧,但似乎无法让我的工作像我想要的那样...... 我正在更改现有的应用程序(.net 3.5使用WPF和C#,实体框架使用sqlserver2008)。我是EFDM和WPF的新手。 新版本需要与以前版本的现有数据库完全兼容,而不对现有数据库进行任何修改,因此我非常不愿意更改数据模型及其生成的任何对象。

无论如何,这是我的问题: 我有来自edm的对象“staffincentive”和“staffincentivelines”,每个员工都有0到多个staffincentiveline附加。 我将它们显示为树视图,并且需要能够动态添加或删除staffincentiveline。

<TreeView ItemsSource="{Binding}" Name="MainTree">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding staffincentiveline}">
        <TextBox Text="{Binding name}"/>
        <Button Tag="{Binding}" Click="addline" Content="Add Line" />
            <HierarchicalDataTemplate.ItemTemplate>
                <DataTemplate >
                        <TextBox Text="{Binding lbound}"/>
                        <TextBox Text="{Binding percentage}"/>
                        <Button Tag="{Binding}" Click="delLine" Content="Remove"/>
                </DataTemplate>
            </HierarchicalDataTemplate.ItemTemplate>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

这样可以正常工作,但是staffincentiveline没有排序,但它们确实需要按顺序出现(升序lbound)。 所以我找了一个解决方案并找到了一个转换器

public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
        {return
((EntityCollection<staffincentiveline>)value).OrderBy(o => o.lbound);}

然后我意识到现在当我使用屏幕上的按钮添加或删除staffincentiveline时,不会显示更改。如果我理解是因为激励线是通过Sort Converter提供的视图显示的,并且在对集合进行更改时不会刷新视图。如果我再次理解正确,这是因为EntityCollection没有实现INotifyPropertyChanged。 如果我使用
刷新视图 CollectionViewSource.GetDefaultView(_incentives).REFRESH();然后所有的树视图都会刷新,所有项目都会被折叠,这对用户来说非常困惑......

那么如何在不改变我的对象类staffincentive和staffincentiveline的情况下进行排序和刷新工作呢?我应该创建另一个包含它们的类并实现INotifyPropertyChanged吗?

由于

1 个答案:

答案 0 :(得分:0)

我设法做到了:)

我创建了2个类StaffIncentiveHelperObject和StaffIncentiveLineHelperObject,它们实现了INotifyPropertyChanged。当通过访问者进行更改时,它们会重叠现有类和触发事件。 您可以使用从StaffIncentiveHelperObject中的ObservableCollection添加/删除StaffIncentiveLineHelperObject的方法,这些方法还可以从EDM中添加/删除原始对象...这是有效地将对视图所做的更改与数据库链接的位。

public class StaffIncentiveHelperObject : INotifyPropertyChanged//
    {
        public delegate void CollectionChangedDelegate();
        public static CollectionChangedDelegate CollectionChanged;

        public StaffIncentiveHelperObject(staffincentive input)
        {
            this._StaffIncentive = input;
        }


        private staffincentive _StaffIncentive;
        public staffincentive StaffIncentive
        {
            get { return _StaffIncentive; }
            set
            {
                if (_StaffIncentive == value) return;
                _StaffIncentive = value;
                OnPropertyChanged("StaffIncentive");
            }
        }

        public decimal? StaffIncentiveIncrement
        {
            get 
            { 
                return _StaffIncentive.increment; 
            }
            set
            {
                if (_StaffIncentive.increment != value)
                {
                    _StaffIncentive.increment = value;
                    OnPropertyChanged("StaffIncentive");
                }
            }
        }

        public string StaffIncentiveName
        {
            get
            {
                return _StaffIncentive.name;
            }
            set
            {
                if (_StaffIncentive.name != value)
                {
                    _StaffIncentive.name = value;
                    OnPropertyChanged("StaffIncentive");
                }
            }
        }

        public byte? StaffIncentiveType
        {
            get
            {
                return _StaffIncentive.type;
            }
            set
            {
                if(_StaffIncentive.type != value)
                {
                    _StaffIncentive.type = value;
                    OnPropertyChanged("StaffIncentive");
                }
            }
        }

        private ObservableCollection<StaffIncentiveLineHelperObject> _StaffIncentiveLines = new ObservableCollection<StaffIncentiveLineHelperObject>();
        public ObservableCollection<StaffIncentiveLineHelperObject> StaffIncentiveLines
        {
            get { return _StaffIncentiveLines; }
            set { _StaffIncentiveLines = value; OnPropertyChanged("StaffIncentiveLines"); }
        }


        public void AddStaffIncentiveLine( staffincentiveline SIL)
        {
            SIL.staffincentive = this._StaffIncentive;
            _StaffIncentive.staffincentiveline.Add(SIL);
            StaffIncentiveLines.Add(new StaffIncentiveLineHelperObject(SIL, this));
            //OnPropertyChanged("StaffIncentiveLine");
            if (CollectionChanged != null)
            {
                CollectionChanged.Invoke();
            }

        }

        public void RemoveStaffIncentiveLine(StaffIncentiveLineHelperObject SILHO)
        {
            _StaffIncentive.staffincentiveline.Remove(SILHO.StaffIncentiveLine);
            _StaffIncentiveLines.Remove(SILHO);
            //OnPropertyChanged("StaffIncentiveLine");
            if (CollectionChanged != null)
            {
                CollectionChanged.Invoke();
            }

        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string name)
        {
            var x = PropertyChanged;
            if (x != null)
                x(this, new PropertyChangedEventArgs(name));
        }

        #endregion
    }

    public class StaffIncentiveLineHelperObject : INotifyPropertyChanged//, INotifyCo
    {
        public StaffIncentiveLineHelperObject(staffincentiveline input, StaffIncentiveHelperObject parent)
        {
            this._StaffIncentiveLine = input;
            this.Parent = parent;
        }


        public StaffIncentiveHelperObject Parent { get; set;}

        private staffincentiveline _StaffIncentiveLine;
        public staffincentiveline StaffIncentiveLine
        {
            get { return _StaffIncentiveLine; }
            set
            {
                if (_StaffIncentiveLine == value) return;
                _StaffIncentiveLine = value;
                OnPropertyChanged("StaffIncentiveLine");
            }
        }

        public decimal? StaffIncentiveLineLbound
        {
            get
            {
                return _StaffIncentiveLine.lbound;
            }
            set
            {
                if (_StaffIncentiveLine.lbound != value)
                {
                    _StaffIncentiveLine.lbound = value;
                    OnPropertyChanged("StaffIncentiveLine");
                }
            }
        }

        public double? StaffIncentiveLinePercentage
        {
            get
            {
                return _StaffIncentiveLine.percentage;
            }
            set
            {
                if (_StaffIncentiveLine.percentage != value)
                {
                    _StaffIncentiveLine.percentage = value;
                    OnPropertyChanged("StaffIncentiveLine");
                }
            }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string name)
        {
            var x = PropertyChanged;
            if (x != null)
                x(this, new PropertyChangedEventArgs(name));

        }

        #endregion
    }

xaml的datacontext设置为ObservableCollection,它只是根据EDM的现有对象构建的,如下所示

ObservableCollection<SupportingObjects.StaffIncentiveHelperObject> myIcentives = new ObservableCollection<SupportingObjects.StaffIncentiveHelperObject>();
foreach (staffincentive SI in db_incentives)
{
    StaffIncentiveHelperObject SIHO = new StaffIncentiveHelperObject(SI);
    myIcentives.Add(SIHO);
    foreach (staffincentiveline SIL in SI.staffincentiveline)
    {
        SIHO.AddStaffIncentiveLine(SIL);
    }
}

然后XAML使用访问者显示/更新它。

<TreeView ItemsSource="{Binding}" Name="MainTree">
<TreeView.ItemTemplate>
    <HierarchicalDataTemplate ItemsSource="{Binding StaffIncentiveLines, Converter={StaticResource IncentiveLineHelperObjectSort}, ConverterParameter=StaffIncentiveLineLbound}">
        <StackPanel Orientation="Horizontal" >
            <TextBox Text="{Binding StaffIncentiveName}" Width="120" />
            <Button Tag="{Binding}" Click="addline" Content="Add Line" />
        </StackPanel>
        <HierarchicalDataTemplate.ItemTemplate>
            <DataTemplate >
                <StackPanel Orientation="Horizontal"  Margin="150,0,0,0">
                    <TextBox Text="{Binding StaffIncentiveLineLbound, StringFormat='{}{0:c}'}" Width="120" />
                    <TextBox Text="{Binding StaffIncentiveLinePercentage}" Width="120" />
                <Button Tag="{Binding}" Click="delLine" Content="Remove"/>
                </StackPanel>
            </DataTemplate>
        </HierarchicalDataTemplate.ItemTemplate>
    </HierarchicalDataTemplate>
</TreeView.ItemTemplate>

排序仅在第一次加载时完成,而不是在添加行时动态完成,这对我来说很好。这是排序转换器(我从网站上的另一个问题复制它)

public class IncentiveLineHelperObjectSort : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            System.Collections.ObjectModel.ObservableCollection<StaffIncentiveLineHelperObject> collection = value as System.Collections.ObjectModel.ObservableCollection<StaffIncentiveLineHelperObject>;
            ListCollectionView view = new ListCollectionView(collection);
            System.ComponentModel.SortDescription sort = new System.ComponentModel.SortDescription(parameter.ToString(), System.ComponentModel.ListSortDirection.Ascending);
            view.SortDescriptions.Add(sort);

            return view;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;
        }
    }

以下是按下按钮时添加或删除staffincentiveline的方法。

private void addline(object sender, RoutedEventArgs e)
        {
            var incentive = ((sender as Button).Tag as StaffIncentiveHelperObject);
            incentive.AddStaffIncentiveLine(new staffincentiveline());
            TreeViewItem thisTreeViewItem = MainTree.ItemContainerGenerator.ContainerFromItem(incentive) as TreeViewItem;
            thisTreeViewItem.IsExpanded = true;
        }

        private void delLine(object sender, RoutedEventArgs e)
        {
            var line = ((sender as Button).Tag as StaffIncentiveLineHelperObject);
            StaffIncentiveHelperObject thisIncentive = line.Parent;

            thisIncentive.RemoveStaffIncentiveLine(line);
            TreeViewItem thisTreeViewItem = MainTree.ItemContainerGenerator.ContainerFromItem(thisIncentive) as TreeViewItem;
            if (thisIncentive.StaffIncentiveLines.Count == 0)
            {

                thisTreeViewItem.IsExpanded = false;
            }
        }

如果其他人有更好的方法或改进方法,我会很高兴听到它:)