2013-08-07 3 views
1

일부 표시를 기반으로하는 목록보기 열의 표시 순서를 xml 파일에서 설정으로 변경해야합니다.이 방법은 코드 숨김없이 xaml에서만 수행 할 수 있습니다. MVVM을 사용하고 있습니다. .목록보기에서 열의 표시 순서를 변경하십시오.

이것은 코드입니다. xml (기본적으로 열 이름의 시퀀스가됩니다)에서 읽은 설정에 따라 열의 순서를 변경하고 싶습니다.

<ListView ItemsSource="{Binding MyList}" > 
<ListView.View > 
     <GridView> 

     <GridViewColumn Header="column1" /> 
     <GridViewColumn Header="column2"/> 
     <GridViewColumn Header="column3" /> 
     <GridViewColumn Header="column4" /> 
     <GridViewColumn Header="column5" /> 
     </GridView> 
    </ListView.View> 
    </ListView> 
+1

당신이 몇 가지 예제를 공유 할 수 코드? –

+0

@ Anand Murali : 샘플 코드. – TRS

답변

0

MVVM 방식으로 수행 할 수 있습니다. GridView.Columns은 종속성 속성이 아니기 때문에 직접 연결된 속성을 정의했습니다. 첨부 된 속성을 정의하려면이 질문을 참조하십시오. 내가 만들었던 샘플 코드를 공유 아래

WPF MVVM: how to bind GridViewColumn to ViewModel-Collection?

. 참고 : 간단하게하기 위해 코드를 사용했지만 코드를 뷰 모델로 매우 잘 옮길 수 있습니다.

GridViewColumns.cs - 속성

을 첨부
using System.Collections.Generic; 
using System.Windows; 
using System.Windows.Controls; 
using System.ComponentModel; 
using System.Windows.Data; 
using System.Collections.Specialized; 
using System.Reflection; 
using System.Collections.ObjectModel; 

namespace WpfApplication1 
{ 
    public static class GridViewColumns 
    { 
     private static NotifyCollectionChangedEventHandler _CollectionChangedEventHandler = null; 

     [AttachedPropertyBrowsableForType(typeof(GridView))] 
     public static object GetColumnsSource(DependencyObject obj) 
     { 
      return (object)obj.GetValue(ColumnsSourceProperty); 
     } 

     public static void SetColumnsSource(DependencyObject obj, object value) 
     { 
      obj.SetValue(ColumnsSourceProperty, value); 
     } 

     // Using a DependencyProperty as the backing store for ColumnsSource. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty ColumnsSourceProperty = 
      DependencyProperty.RegisterAttached(
       "ColumnsSource", 
       typeof(object), 
       typeof(GridViewColumns), 
       new UIPropertyMetadata(
        null, 
        ColumnsSourceChanged)); 


     [AttachedPropertyBrowsableForType(typeof(GridView))] 
     public static string GetHeaderTextMember(DependencyObject obj) 
     { 
      return (string)obj.GetValue(HeaderTextMemberProperty); 
     } 

     public static void SetHeaderTextMember(DependencyObject obj, string value) 
     { 
      obj.SetValue(HeaderTextMemberProperty, value); 
     } 

     // Using a DependencyProperty as the backing store for HeaderTextMember. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty HeaderTextMemberProperty = 
      DependencyProperty.RegisterAttached("HeaderTextMember", typeof(string), typeof(GridViewColumns), new UIPropertyMetadata(null)); 


     [AttachedPropertyBrowsableForType(typeof(GridView))] 
     public static string GetDisplayMemberMember(DependencyObject obj) 
     { 
      return (string)obj.GetValue(DisplayMemberMemberProperty); 
     } 

     public static void SetDisplayMemberMember(DependencyObject obj, string value) 
     { 
      obj.SetValue(DisplayMemberMemberProperty, value); 
     } 

     // Using a DependencyProperty as the backing store for DisplayMember. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty DisplayMemberMemberProperty = 
      DependencyProperty.RegisterAttached("DisplayMemberMember", typeof(string), typeof(GridViewColumns), new UIPropertyMetadata(null)); 


     private static void ColumnsSourceChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
     { 
      GridView gridView = obj as GridView; 
      if (gridView != null) 
      { 
       gridView.Columns.Clear(); 

       if (e.OldValue != null) 
       { 
        ICollectionView view = CollectionViewSource.GetDefaultView(e.OldValue); 
        if (view != null) 
         RemoveHandlers(gridView, view); 
       } 

       if (e.NewValue != null) 
       { 
        ICollectionView view = CollectionViewSource.GetDefaultView(e.NewValue); 
        if (view != null) 
        { 
         AddHandlers(gridView, view); 
         CreateColumns(gridView, view); 
        } 
       } 
      } 
     } 

     private static IDictionary<ICollectionView, List<GridView>> _gridViewsByColumnsSource = 
      new Dictionary<ICollectionView, List<GridView>>(); 

     private static List<GridView> GetGridViewsForColumnSource(ICollectionView columnSource) 
     { 
      List<GridView> gridViews; 
      if (!_gridViewsByColumnsSource.TryGetValue(columnSource, out gridViews)) 
      { 
       gridViews = new List<GridView>(); 
       _gridViewsByColumnsSource.Add(columnSource, gridViews); 
      } 
      return gridViews; 
     } 

     private static void AddHandlers(GridView gridView, ICollectionView view) 
     { 
      GetGridViewsForColumnSource(view).Add(gridView); 
      view.CollectionChanged += ColumnsSource_CollectionChanged; 

      _CollectionChangedEventHandler = delegate(object sender, NotifyCollectionChangedEventArgs e) 
      { 
       var source = view.SourceCollection as ObservableCollection<ColumnDescriptor>; 
       if (source != null && e.Action == NotifyCollectionChangedAction.Move) 
         source.Move(e.OldStartingIndex, e.NewStartingIndex); 
      }; 
      gridView.Columns.CollectionChanged += _CollectionChangedEventHandler; 
     } 

     private static void CreateColumns(GridView gridView, ICollectionView view) 
     { 
      foreach (var item in view) 
      { 
       GridViewColumn column = CreateColumn(gridView, item); 
       gridView.Columns.Add(column); 
      } 
     } 

     private static void RemoveHandlers(GridView gridView, ICollectionView view) 
     { 
      view.CollectionChanged -= ColumnsSource_CollectionChanged; 
      GetGridViewsForColumnSource(view).Remove(gridView); 
      gridView.Columns.CollectionChanged -= _CollectionChangedEventHandler; 
     } 

     private static void ColumnsSource_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
     { 
      ICollectionView view = sender as ICollectionView; 
      var gridViews = GetGridViewsForColumnSource(view); 
      if (gridViews == null || gridViews.Count == 0) 
       return; 

      switch (e.Action) 
      { 
       case NotifyCollectionChangedAction.Add: 
        foreach (var gridView in gridViews) 
        { 
         for (int i = 0; i < e.NewItems.Count; i++) 
         { 
          GridViewColumn column = CreateColumn(gridView, e.NewItems[i]); 
          gridView.Columns.Insert(e.NewStartingIndex + i, column); 
         } 
        } 
        break; 
       case NotifyCollectionChangedAction.Move: 
        foreach (var gridView in gridViews) 
        { 
         List<GridViewColumn> columns = new List<GridViewColumn>(); 
         for (int i = 0; i < e.OldItems.Count; i++) 
         { 
          GridViewColumn column = gridView.Columns[e.OldStartingIndex + i]; 
          columns.Add(column); 
         } 
         for (int i = 0; i < e.NewItems.Count; i++) 
         { 
          GridViewColumn column = columns[i]; 

          // Check if column exists 
          if (gridView.Columns.Contains(columns[i]) == false) 
          gridView.Columns.Insert(e.NewStartingIndex + i, column); 
         } 
        } 
        break; 
       case NotifyCollectionChangedAction.Remove: 
        foreach (var gridView in gridViews) 
        { 
         for (int i = 0; i < e.OldItems.Count; i++) 
         { 
          gridView.Columns.RemoveAt(e.OldStartingIndex); 
         } 
        } 
        break; 
       case NotifyCollectionChangedAction.Replace: 
        foreach (var gridView in gridViews) 
        { 
         for (int i = 0; i < e.NewItems.Count; i++) 
         { 
          GridViewColumn column = CreateColumn(gridView, e.NewItems[i]); 
          gridView.Columns[e.NewStartingIndex + i] = column; 
         } 
        } 
        break; 
       case NotifyCollectionChangedAction.Reset: 
        foreach (var gridView in gridViews) 
        { 
         gridView.Columns.Clear(); 
         CreateColumns(gridView, sender as ICollectionView); 
        } 
        break; 
       default: 
        break; 
      } 
     } 

     private static GridViewColumn CreateColumn(GridView gridView, object columnSource) 
     { 
      GridViewColumn column = new GridViewColumn(); 
      string headerTextMember = GetHeaderTextMember(gridView); 
      string displayMemberMember = GetDisplayMemberMember(gridView); 
      if (!string.IsNullOrEmpty(headerTextMember)) 
      { 
       column.Header = GetPropertyValue(columnSource, headerTextMember); 
      } 
      if (!string.IsNullOrEmpty(displayMemberMember)) 
      { 
       string propertyName = GetPropertyValue(columnSource, displayMemberMember) as string; 
       column.DisplayMemberBinding = new Binding(propertyName); 
      } 
      return column; 
     } 

     private static object GetPropertyValue(object obj, string propertyName) 
     { 
      if (obj != null) 
      { 
       PropertyInfo prop = obj.GetType().GetProperty(propertyName); 
       if (prop != null) 
        return prop.GetValue(obj, null); 
      } 
      return null; 
     } 
    } 
} 

XAML :

<Window x:Class="WpfApplication1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:WpfApplication1" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto"/> 
      <RowDefinition Height="*"/> 
     </Grid.RowDefinitions> 
     <Button Content="Change Order" Click="Button_Click" Width="120" Margin="5"/> 
     <ListView Grid.Row="1" ItemsSource="{Binding MyList}" > 
      <ListView.View > 
       <GridView local:GridViewColumns.HeaderTextMember="HeaderText" 
         local:GridViewColumns.DisplayMemberMember="DisplayMember" 
         local:GridViewColumns.ColumnsSource="{Binding OrderedColumns}"> 
       </GridView> 
      </ListView.View> 
     </ListView> 
    </Grid> 
</Window> 

코드 숨김

using System.Collections.Generic; 
using System.Windows; 
using System.Collections.ObjectModel; 

namespace WpfApplication1 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     private ViewModel _ViewModel = null; 
     public MainWindow() 
     { 
      InitializeComponent(); 

      _ViewModel = new ViewModel(); 
      this.DataContext = _ViewModel; 
     } 

     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      // Moves the first column to the last 
      var temp = _ViewModel.OrderedColumns[0]; 
      _ViewModel.OrderedColumns.Remove(temp); 
      _ViewModel.OrderedColumns.Add(temp); 

     } 
    } 

    public class ViewModel 
    { 
     private ObservableCollection<ColumnDescriptor> _OrderedColumns; 

     public ObservableCollection<ColumnDescriptor> OrderedColumns 
     { 
      get { return _OrderedColumns; } 
      set { _OrderedColumns = value; } 
     } 

     private List<Customer> _MyList; 

     public List<Customer> MyList 
     { 
      get { return _MyList; } 
      set { _MyList = value; } 
     } 


     public ViewModel() 
     { 
      OrderedColumns = new ObservableCollection<ColumnDescriptor>(); 
      OrderedColumns.Add(new ColumnDescriptor() { HeaderText = "Column1", DisplayMember = "Column1" }); 
      OrderedColumns.Add(new ColumnDescriptor() { HeaderText = "Column2", DisplayMember = "Column2" }); 
      OrderedColumns.Add(new ColumnDescriptor() { HeaderText = "Column3", DisplayMember = "Column3" }); 
      OrderedColumns.Add(new ColumnDescriptor() { HeaderText = "Column4", DisplayMember = "Column4" }); 

      MyList = new List<Customer>(); 

      MyList.Add(new Customer() { Column1 = "Data_Col1", Column2 = "Data_Col2", Column3 = "Data_Col3", Column4 = "Data_Col4" }); 
      MyList.Add(new Customer() { Column1 = "2Data_Col1", Column2 = "2Data_Col2", Column3 = "2Data_Col3", Column4 = "2Data_Col4" }); 
     } 
    } 

    public class ColumnDescriptor 
    { 
     public string HeaderText { get; set; } 
     public string DisplayMember { get; set; } 
    } 

    public class Customer 
    { 
     public string Column1 { get; set; } 
     public string Column2 { get; set; } 
     public string Column3 { get; set; } 
     public string Column4 { get; set; } 
    } 
} 
+0

굉장한 ... 나의 날을 구했다. – TRS

+0

Can 다른 방법으로도 작업 할 수 있습니다. 예를 들어 사용자가보기에서 열 순서를 변경하고보기 모델에서 열을 변경하는 것처럼 말입니다. – TRS

+0

예 가능합니다. 나는 대답을 편집했다. –

-1

이유는 무엇입니까? 걱정의 분리는 좋지만, 당신의 견해를 스타일링하기 위해 코드를 사용한다면 나는 여전히 방어 할 수 있다고 생각합니다.

+0

죄송합니다. 내 질문은 codebehind와 MVVM 사이의 논쟁을위한 것이 아닙니다. 단지 MVVM에서 할 수있는 방법이 있는지 묻습니다. 관리자 : 질문을 닫지 마십시오. – TRS

관련 문제