【问题标题】:Self-referensed entity to wpf treeview using Binding Converter and ObservableCollection使用 Binding Converter 和 ObservableCollection 自引用实体到 wpf 树视图
【发布时间】:2013-05-15 22:10:16
【问题描述】:

我有实体,默认从引用自身的数据库表构建

我是新来的,声誉低,我不能添加图片,所以我会写我能写的。

区域:实体对象

属性:

身份证

ParentArea_ID

导航属性:

Areas - 区域集合

ParentArea - 实例化区域

我想用数据库表中的数据填充树视图。我找到了 2 个选项:使用来自 here 的包装器或绑定转换器。我是初学者,可能是错的,但使用 Binding Converter 对我来说是更好的方法。

我发现我必须使用 Areas 集合创建一个新类,以便更轻松地实现导航、添加、删除

class AreasCollection:ObservableCollection<Area>
{
    private DBEntities _context;
    
    public DBEntities Context
    {
        get { return _context; }
    }

    public AreasCollection(IEnumerable<Area> Areas, DBEntities context)
        : base(Areas)
    {
        _context = context;
        foreach (Area a in Areas)
        {
            a.Areas.AssociationChanged +=new CollectionChangeEventHandler(Areas_AssociationChanged);
        }
    }

    void Areas_AssociationChanged(object sender, CollectionChangeEventArgs e)
    {
        if (e.Action == CollectionChangeAction.Remove)
        {
            this.Context.DeleteObject((Area)e.Element);
            this.Context.DeleteObject((SpareDevice)e.Element);
            this.Context.DeleteObject((AreaDevice)e.Element);
            this.Context.DeleteObject((Executor)e.Element);
        }
    }

    protected override void InsertItem(int index, Area item)
    {
        item.Areas.AssociationChanged += new CollectionChangeEventHandler(Areas_AssociationChanged);
        this.Context.AddToAreas(item);
        base.InsertItem(index, item);
    }

    protected override void RemoveItem(int index)
    {
        Area a = this[index];
        a.Areas.AssociationChanged -= Areas_AssociationChanged;
        for (int i = a.Areas.Count - 1; i >= 0; i--)
        {
            this.Context.DeleteObject(a.Areas.ElementAt(i));
        } 
        for (int i = a.SpareDevices.Count - 1; i >= 0; i--)
        {
            this.Context.DeleteObject(a.SpareDevices.ElementAt(i));
        }
        for (int i = a.AreaDevices.Count - 1; i >= 0; i--)
        {
            this.Context.DeleteObject(a.AreaDevices.ElementAt(i));
        }
        for (int i = a.Executors.Count - 1; i >= 0; i--)
        {
            this.Context.DeleteObject(a.Executors.ElementAt(i));
        }
        this.Context.DeleteObject(this[index]);
        base.RemoveItem(index);
    }
}

我发现我必须做一个新的转换器类

public class AreasConverter : IValueConverter
{
    public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var item = value as Area;
        return item.Areas.Where(a => a.ParentArea_ID == item.ID);
    }

    public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

我的 XAML:

    <TreeView Name="AreasTreeView" Height="350" ItemsSource="{Binding Converter={StaticResource AreasConverter}}"  ItemTemplate="{StaticResource ItemTemplate}">
    <TreeView.Resources>
        <local:AreasConverter x:Key="AreasConverter"/>
        <HierarchicalDataTemplate x:Key="ItemTemplate" ItemsSource="{Binding Converter={StaticResource AreasConverter}}">
            <TextBlock Text="{Binding Path=ShortName}" />
        </HierarchicalDataTemplate>
    </TreeView.Resources>
    </TreeView>

还有 XAML.cs

public partial class MainWindow : Window
{
    private DBEntities context = new DBEntities();
    private CollectionViewSource AreasConverterViewSourse;
    private ListCollectionView AreasConverter;


    public MainWindow()
    {
        InitializeComponent();
        AreasTreeView.ItemsSource = context.Areas.Where(a => a.ParentArea_ID == null);
        AreasConverterViewSourse = (CollectionViewSource)FindResource("AreasConverter");
        this.AreasConverter = (ListCollectionView)this.AreasConverterViewSourse.View;

    }
}

我有一个错误资源“ItemTemplate”无法解析。

如果我删除 ItemTemplate="{StaticResource ItemTemplate}"

来自

    <TreeView Name="AreasTreeView" Height="350" ItemsSource="{Binding Converter={StaticResource AreasConverter}}"  ItemTemplate="{StaticResource ItemTemplate}">

错误消失了,但是当我尝试运行应用程序时出现异常

System.Windows.Markup.XamlParseException occurred
  HResult=-2146233087
  Message='Provide value on 'System.Windows.StaticResourceExtension' threw an exception.' Line number '30' and line position '61'.
  Source=PresentationFramework
  LineNumber=30
  LinePosition=61
  StackTrace:
      at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri) 
      at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri)
      at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
      at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
      at Maintenance.MainWindow.InitializeComponent() in  c:\DATA\Maintenance\Maintenance\MainWindow.xaml:line 1
      at Maintenance.MainWindow..ctor() in c:\DATA\Maintenance\Maintenance\MainWindow.xaml.cs:line 44
  InnerException: 
       HResult=-2146233088
       Message=Cannot find resource named 'AreasConverter'. Resource names are case sensitive.
       Source=PresentationFramework
       StackTrace:
            at System.Windows.StaticResourceExtension.ProvideValue(IServiceProvider serviceProvider)
            at MS.Internal.Xaml.Runtime.ClrObjectRuntime.CallProvideValue(MarkupExtension me, IServiceProvider serviceProvider)
       InnerException: 

这是我的第一个 wpf 应用程序和第一个数据库设计(16 个表)。从入门 sql server 和 wpf 视频开始,我已经为这个项目花费了 6 个弱点,谷歌搜索了几个小时和天。我的大脑开始沸腾。如果答案尽可能详细,我很乐意。

感谢您的帮助!

【问题讨论】:

    标签: wpf binding treeview entity self-reference


    【解决方案1】:

    下面的工作解决方案

    XAML:

        <Window.Resources>
            <local:AreasConverter x:Key="AreasConverter"/>
        </Window.Resources>
    
    
                <TreeView Name="AreasTreeView" Height="350">
                    <TreeView.ItemTemplate>
                        <HierarchicalDataTemplate ItemsSource="{Binding Converter={StaticResource AreasConverter}}">
                            <TextBlock Text="{Binding Path=ShortName}" />
                        </HierarchicalDataTemplate>
                    </TreeView.ItemTemplate>
                </TreeView>
    

    ObservableCollection cs:

    class AreasCollection:ObservableCollection<Area>
    {
        private DBEntities _context;
    
        public DBEntities Context
        {
            get { return _context; }
        }
    
        public AreasCollection(IEnumerable<Area> Areas, DBEntities context)
            : base(Areas)
        {
            _context = context;
            foreach (Area a in Areas)
            {
                a.Areas.AssociationChanged +=new CollectionChangeEventHandler(Areas_AssociationChanged);
            }
        }
    
        void Areas_AssociationChanged(object sender, CollectionChangeEventArgs e)
        {
            if (e.Action == CollectionChangeAction.Remove)
            {
                this.Context.DeleteObject((Area)e.Element);
                this.Context.DeleteObject((SpareDevice)e.Element);
                this.Context.DeleteObject((AreaDevice)e.Element);
                this.Context.DeleteObject((Executor)e.Element);
            }
        }
    
        protected override void InsertItem(int index, Area item)
        {
            item.Areas.AssociationChanged += new CollectionChangeEventHandler(Areas_AssociationChanged);
            this.Context.AddToAreas(item);
            base.InsertItem(index, item);
        }
    
        protected override void RemoveItem(int index)
        {
            Area a = this[index];
            a.Areas.AssociationChanged -= Areas_AssociationChanged;
            for (int i = a.Areas.Count - 1; i >= 0; i--)
            {
                this.Context.DeleteObject(a.Areas.ElementAt(i));
            } 
            for (int i = a.SpareDevices.Count - 1; i >= 0; i--)
            {
                this.Context.DeleteObject(a.SpareDevices.ElementAt(i));
            }
            for (int i = a.AreaDevices.Count - 1; i >= 0; i--)
            {
                this.Context.DeleteObject(a.AreaDevices.ElementAt(i));
            }
            for (int i = a.Executors.Count - 1; i >= 0; i--)
            {
                this.Context.DeleteObject(a.Executors.ElementAt(i));
            }
            this.Context.DeleteObject(this[index]);
            base.RemoveItem(index);
        }
    }
    

    转换器类cs:

    public class AreasConverter : IValueConverter
    {
        public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var item = value as Area;
            return item.Areas.Where(a => a.ParentArea_ID == item.ID);
        }
    
        public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    XAML.cs:

        public MainWindow()
        {
            InitializeComponent();
            AreasTreeView.ItemsSource = context.Areas.Where(a => a.ParentArea_ID == null);
        }
    

    【讨论】:

      猜你喜欢
      • 2017-02-18
      • 2015-04-23
      • 1970-01-01
      • 2012-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-26
      • 2014-11-01
      相关资源
      最近更新 更多