■ TreeView 클래스 : 데이터 바인딩시 부모 노드 사전 설정하기

------------------------------------------------------------------------------------------------------------------------


TestProject.zip


IParentLink.cs

 

 

using System.Windows.Controls;

 

namespace TestProject

{

    /// <summary>

    /// 부모 연결 인터페이스

    /// </summary>

    public interface IParentLink

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 부모 트리뷰 아이템 - ParentTreeViewItem

 

        /// <summary>

        /// 부모 트리뷰 아이템

        /// </summary>

        TreeViewItem ParentTreeViewItem { get; set; }

 

        #endregion

    }

}

 

 

ParentLinkItem.cs

 

 

using System.ComponentModel;

using System.Windows.Controls;

 

namespace TestProject

{

    /// <summary>

    /// 부모 연결 아이템

    /// </summary>

    public class ParentLinkItem : INotifyPropertyChanged, IParentLink

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Event

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 속성 변경시 이벤트 - PropertyChanged

 

        /// <summary>

        /// 속성 변경시 이벤트

        /// </summary>

        public event PropertyChangedEventHandler PropertyChanged;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 명칭

        /// </summary>

        private string name;

 

        /// <summary>

        /// 부모 트리뷰 아이템

        /// </summary>

        private TreeViewItem parentTreeViewItem;

 

        /// <summary>

        /// 자식 리스트

        /// </summary>

        private BindingList<ParentLinkItem> childList;

 

        /// <summary>

        /// 선택 여부

        /// </summary>

        private bool isSelected;

 

        /// <summary>

        /// 확장 여부

        /// </summary>

        private bool isExpanded;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 명칭 - Name

 

        /// <summary>

        /// 명칭

        /// </summary>

        public string Name

        {

            get

            {

                return this.name;

            }

            set

            {

                this.name = value;

                

                FirePropertyChangedEvent("Name");

            }

        }

 

        #endregion

        #region 부모 트리뷰 아이템 - ParentTreeViewItem

 

        /// <summary>

        /// 부모 트리뷰 아이템

        /// </summary>

        public TreeViewItem ParentTreeViewItem

        {

            get

            {

                return this.parentTreeViewItem;

            }

            set

            {

                this.parentTreeViewItem = value;

            }

        }

 

        #endregion

        #region 부모 - Parent

 

        /// <summary>

        /// 부모

        /// </summary>

        public ParentLinkItem Parent

        {

            get

            {

                if(this.parentTreeViewItem == null)

                {

                    return null;

                }

 

                return this.parentTreeViewItem.DataContext as ParentLinkItem;

            }

        }

 

        #endregion

        #region 자식 리스트 - ChildList

 

        /// <summary>

        /// 자식 리스트

        /// </summary>

        public BindingList<ParentLinkItem> ChildList

        {

            get

            {

                return this.childList;

            }

            set

            {

                this.childList = value;

 

                FirePropertyChangedEvent("ChildList");

            }

        }

 

        #endregion

        #region 선택 여부 - IsSelected

 

        /// <summary>

        /// 선택 여부

        /// </summary>

        public bool IsSelected

        {

            get

            {

                return this.isSelected;

            }

            set

            {

                this.isSelected = value;

                

                FirePropertyChangedEvent("IsSelected");

            }

        }

 

        #endregion

        #region 확장 여부 - IsExpanded

 

        /// <summary>

        /// 확장 여부

        /// </summary>

        public bool IsExpanded

        {

            get

            {

                return this.isExpanded;

            }

            set

            {

                this.isExpanded = value;

                

                FirePropertyChangedEvent("IsExpanded");

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 속성 변경시 이벤트 발생시키기 - FirePropertyChangedEvent(propertyName)

 

        /// <summary>

        /// 속성 변경시 이벤트 발생시키기

        /// </summary>

        /// <param name="propertyName">속성명</param>

        public virtual void FirePropertyChangedEvent(string propertyName)

        {

            if(PropertyChanged != null)

            {

                PropertyChangedEventArgs e = new PropertyChangedEventArgs(propertyName);

 

                PropertyChanged(this, e);

            }

        }

 

        #endregion

    }

}

 

 

ParentLinkTreeViewItem.cs

 

 

using System.Windows;

using System.Windows.Controls;

 

namespace TestProject

{

    /// <summary>

    /// 부모 연결 트리뷰 아이템

    /// </summary>

    public class ParentLinkTreeViewItem : TreeViewItem

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - ParentLinkTreeViewItem()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public ParentLinkTreeViewItem() : base()

        {

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Protected

 

        #region 아이템에서 컨테이너 준비하기 (오버라이딩) - PrepareContainerForItemOverride(element, item)

 

        /// <summary>

        /// 아이템을 위한 컨테이너 준비하기 (오버라이딩)

        /// </summary>

        /// <param name="element">엘리먼트</param>

        /// <param name="item">아이템</param>

        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)

        {

            base.PrepareContainerForItemOverride(element, item);

 

            IParentLink parentLink = item as IParentLink;

 

            if(parentLink == null)

            {

                return;

            }

 

            parentLink.ParentTreeViewItem = ItemsControl.ItemsControlFromItemContainer(element) as TreeViewItem;

        }

 

        #endregion

        #region 아이템을 위한 컨테이너 구하기 (오버라이딩) - GetContainerForItemOverride()

 

        /// <summary>

        /// 아이템을 위한 컨테이너 구하기 (오버라이딩)

        /// </summary>

        /// <returns>의존 객체</returns>

        protected override DependencyObject GetContainerForItemOverride()

        {

            return new ParentLinkTreeViewItem();

        }

 

        #endregion

    }

}

 

 

ParentLinkTreeView.cs

 

 

using System.Windows;

using System.Windows.Controls;

 

namespace TestProject

{

    /// <summary>

    /// 부모 연결 트리뷰

    /// </summary>

    public class ParentLinkTreeView : TreeView

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Protected

 

        #region 아이템을 위한 컨테이너 구하기 (오버라이딩) - GetContainerForItemOverride()

 

        /// <summary>

        /// 아이템을 위한 컨테이너 구하기 (오버라이딩)

        /// </summary>

        /// <returns>의존 객체</returns>

        protected override DependencyObject GetContainerForItemOverride()

        {

            return new ParentLinkTreeViewItem();

        }

 

        #endregion

    }

}

 

 

MainWindow.xaml

 

 

<Window x:Class="TestProject.MainWindow"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:local="clr-namespace:TestProject"

    Width="800"

    Height="600"

    Title="TreeView 클래스 : 데이터 바인딩시 부모 노드 사전 설정하기"

    FontFamily="나눔고딕코딩"

    FontSize="16">

    <Grid>

        <local:ParentLinkTreeView x:Name="treeView"

            VirtualizingStackPanel.VirtualizationMode="Standard"

            VirtualizingStackPanel.IsVirtualizing="False">

            <local:ParentLinkTreeView.ItemContainerStyle>

                <Style TargetType="{x:Type TreeViewItem}">

                    <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />

                    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />

                </Style>

            </local:ParentLinkTreeView.ItemContainerStyle>

            <local:ParentLinkTreeView.ItemTemplate>

                <HierarchicalDataTemplate ItemsSource="{Binding ChildList}">

                    <TextBlock Text="{Binding Name}" />

                </HierarchicalDataTemplate>

            </local:ParentLinkTreeView.ItemTemplate>

        </local:ParentLinkTreeView>

    </Grid>

</Window>

 

 

MainWindow.xaml.cs

 

 

using System.ComponentModel;

using System.Windows;

 

namespace TestProject

{

    /// <summary>

    /// 메인 윈도우

    /// </summary>

    public partial class MainWindow

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 소스 리스트

        /// </summary>

        private BindingList<ParentLinkItem> sourceList = new BindingList<ParentLinkItem>();

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 소스 리스트 - SourceList

 

        /// <summary>

        /// 소스 리스트

        /// </summary>

        public BindingList<ParentLinkItem> SourceList

        {

            get

            {

                return this.sourceList;

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - MainWindow()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainWindow()

        {

            InitializeComponent();

 

            Loaded                            += Window_Loaded;

            this.treeView.SelectedItemChanged += treeView_SelectedItemChanged;

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region 윈도우 로드시 처리하기 - Window_Loaded(sender, e)

 

        /// <summary>

        /// 윈도우 로드시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void Window_Loaded(object sender, RoutedEventArgs e)

        {

            for(int i = 0; i < 2; i++)

            {

                ParentLinkItem item1 = new ParentLinkItem();

 

                item1.Name = "부모 노드 " + i.ToString();

 

                item1.ChildList  = new BindingList<ParentLinkItem>();

                item1.IsExpanded = true;

 

                for(int j = 0; j < 5; j++)

                {

                    ParentLinkItem item2 = new ParentLinkItem();

 

                    item2.Name = "자식 노드 " + i.ToString() + "_" + j.ToString();

                    item2.IsExpanded = true;

 

                    item1.ChildList.Add(item2);

                }

 

                this.sourceList.Add(item1);

 

                this.treeView.ItemsSource = this.sourceList;

            }

        }

 

        #endregion

        #region 트리뷰 선택 아이템 변경시 처리하기 - treeView_SelectedItemChanged(sender, e)

 

        /// <summary>

        /// 트리뷰 선택 아이템 변경시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void treeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)

        {

            ParentLinkItem item = e.NewValue as ParentLinkItem;

 

            if(item.Parent == null)

            {

                return;

            }

 

            MessageBox.Show(this, item.Parent.Name);

        }

 

        #endregion

    }

}

 

------------------------------------------------------------------------------------------------------------------------

Posted by 사용자 icodebroker
TAG