zoukankan      html  css  js  c++  java
  • WPF中遇到的一些问题总结

    1.近日想实现一个功能,在tabcontrol中动态添加tabitem,每个tabitem中显示的数据模型一样,但是数据内容不一样。第一想法就是自定义一个tabitem的模板,然后这个模板中可以包含一个usercontrol来组织我的数据模型。当初的实现如图中注释代码所示:

     在ContentTemplate中设置一个DataTemplate,DataTemplate中包含一个自定义Usercontrol,名称为TabItemWithGraphic,主要是在Tabitem中实现绘图功能。通过测试发现每个TabItem都能根据数据绘图,但是当切换某个TabItem的数据值是,所有的TabItem都会同时改变,显然不符合预期。一点点琢磨并查找各种资料,终于在Stack Overflow上找到了问题的本质原因,那就是关于模板的使用。模板是一种资源,是可以供所有满足要求的元素公用共享的,运行时只有一份,如此一来若我们将Usercontrol放置在模板中,那岂不是这个Usercontrol是对所有Tabitem共享,可以想到当把其中一个Tabitem数据更改时,则Usercontrol显示内容发生变化,由此导致其他的Tabitem中显示数据也发生变化。
    找到了问题的根本原因,问题就好解决了,那就是我们不能把Usercontrol直接放置在模板中,而是根据需要每个Tabitem中实例化一个自己的usercontrol,便可以解决问题,如果你用的是MVVM开发的话,发现会比较繁琐了。因为相比起来要自己写代码来初始化Usercontrol等操作而言,能直接定义在模板中,并将数据源绑定到Tabcontrol的Source上确实是要麻烦多了。可惜Stack Overflow的链接我自己目前找不到了,大概讲一下,就是给自定义一个附加属性CachedItemsSource,然后根据这个Source的变化来动态增加或减少包含Usercontrol的TabItem。最后附上参考的解决办法:

    /*
    *---------------------------------
    *|        All rights reserved.
    *|        author: lizhanping
    *|        version:1.0
    *|        File: TabControlExtension.cs
    *|        Summary: 
    *|        Date: 2020/1/9 15:28:40
    *---------------------------------
    */
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    
    namespace TabControlTest
    {
        public static class TabControlExtension
        {      
    
            // Custom DependencyProperty for a CachedItemsSource
            public static readonly DependencyProperty CachedItemsSourceProperty =
                DependencyProperty.RegisterAttached("CachedItemsSource", typeof(IList), typeof(TabControlExtension), new PropertyMetadata(null, CachedItemsSource_Changed));
    
            // Get items
            public static IList GetCachedItemsSource(DependencyObject dependencyObject)
            {
                return dependencyObject?.GetValue(CachedItemsSourceProperty) as IList;
            }
    
            // Set items
            public static void SetCachedItemsSource(DependencyObject dependencyObject, IEnumerable value)
            {
                dependencyObject?.SetValue(CachedItemsSourceProperty, value);
            }
    
             
            // Change Event
            public static void CachedItemsSource_Changed(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
            {
                if (!(dependencyObject is TabControl))
                    return;
                TabControl tabControl = dependencyObject as TabControl;
                var changeAction = new NotifyCollectionChangedEventHandler(
                    (o, args) =>
                    {
                        if (GetCachedItemsSource(tabControl) != null)
                            UpdateTabItems(tabControl);
                    });
    
                // if the bound property is an ObservableCollection, attach change events
                if (e.OldValue is INotifyCollectionChanged)
                {
                    INotifyCollectionChanged oldValue = e.OldValue as INotifyCollectionChanged;
                    oldValue.CollectionChanged -= changeAction;
                }
    
                if (e.NewValue is INotifyCollectionChanged)
                {
                    INotifyCollectionChanged newValue = e.NewValue as INotifyCollectionChanged;
                    newValue.CollectionChanged += changeAction;
                }
    
                if (GetCachedItemsSource(dependencyObject) != null)
                    UpdateTabItems(dependencyObject as TabControl);
        }
    
            private static void UpdateTabItems(TabControl tabControl)
            {
                if (tabControl == null)
                    return;
    
                IList itemsSource = GetCachedItemsSource(tabControl);
    
                if (itemsSource == null || itemsSource.Count == 0)
                {
                    if (tabControl.Items.Count > 0)
                        tabControl.Items.Clear();
    
                    return;
                }
    
    
                // loop through items source and make sure datacontext is correct for each one
                for (int i = 0; i < itemsSource.Count; i++)
                {
                    if (tabControl.Items.Count <= i)
                    {
                        TabItem tabItem = new TabItem();
                        CustomTabItem Source = itemsSource[i] as CustomTabItem;
                        tabItem.Header = Source.Header;
                        TabItemWithGraphic content = new TabItemWithGraphic();
                        Binding binding = new Binding();
                        binding.Source = Source;
                        binding.Path = new PropertyPath("Content");
                        BindingOperations.SetBinding(content, TabItemWithGraphic.DataModelProperty, binding);
                        tabItem.Content = content;
                        tabControl.Items.Add(tabItem);
                        tabControl.SelectedItem = tabItem;
                        continue;
                    }
    
                   
                    //current.DataContext = itemsSource[i];
                }
    
                for(int i=0;i< itemsSource.Count;i++)
                {
                    TabItem current = tabControl.Items[i] as TabItem;
                    if (!(tabControl.Items[i] is TabItem))
                        continue;
    
                    if (current.Header.ToString() == (itemsSource[i] as CustomTabItem).Header)
                        continue;
                    else
                    {
                        tabControl.Items.Remove(current);
                        i--;
                    }
                }
    
                // loop backwards and cleanup extra tabs
                for (int i = tabControl.Items.Count; i > itemsSource.Count; i--)
                {
                    tabControl.Items.RemoveAt(i - 1);
                }
            }
        }
    }



  • 相关阅读:
    leetcode 13. Roman to Integer
    python 判断是否为有效域名
    leetcode 169. Majority Element
    leetcode 733. Flood Fill
    最大信息系数——检测变量之间非线性相关性
    leetcode 453. Minimum Moves to Equal Array Elements
    leetcode 492. Construct the Rectangle
    leetcode 598. Range Addition II
    leetcode 349. Intersection of Two Arrays
    leetcode 171. Excel Sheet Column Number
  • 原文地址:https://www.cnblogs.com/chyshx/p/12204594.html
Copyright © 2011-2022 走看看