[Silverlight][C#] 要顯示哪些欄位,給使用者決定!! - 在執行時期動態的顯示/隱藏DataGrid中的欄位

  • 8229
  • 0
  • C#
  • 2013-07-15

今天在MSDN論壇回答問題的時候,看到有人在問說要怎麼在執行時期動態的顯示或是隱藏欄位,雖然我不清楚他確切的需求,不過基於好奇心和好勝心作怪,我還是寫出了下面這個範例~
有興趣的朋友可以參考看看,如果有想到什麼情境下或是這樣的功能很適合用在什麼地方的話,也歡迎留個言交流一下喔!!

 

今天在MSDN論壇回答問題的時候,看到有人在問說要怎麼在執行時期動態的顯示或是隱藏欄位,雖然我不清楚他確切的需求,不過基於好奇心和好勝心作怪,我還是寫出了下面這個範例~

有興趣的朋友可以參考看看,如果有想到什麼情境下或是這樣的功能很適合用在什麼地方的話,也歡迎留個言交流一下喔!!

 

先來看看Xaml原始碼:

MainPage.xaml

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
		xmlns:theme="clr-namespace:System.Windows.Controls.Theming;assembly=System.Windows.Controls.Theming.ExpressionDark"
		xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" x:Class="SL_DynamicDataGridColumns.MainPage"
		mc:Ignorable="d" d:DesignHeight="600" d:DesignWidth="800">
	<theme:ExpressionDarkTheme Background="{x:Null}" Foreground="#FF646464">
		<Border BorderThickness="2" CornerRadius="10" Margin="10" Background="White" BorderBrush="#FF646464">
			<Border.Effect>
				<DropShadowEffect />
			</Border.Effect>
			<Grid x:Name="LayoutRoot" Background="Transparent">
				<Grid.RowDefinitions>
					<RowDefinition Height="40" />
					<RowDefinition />
					<RowDefinition Height="Auto" />
				</Grid.RowDefinitions>
				<TextBlock HorizontalAlignment="Center" TextWrapping="Wrap" Text="Silverlight動態顯示DataGrid欄位範例"
						VerticalAlignment="Center" FontSize="26.667" FontWeight="Bold" />
				<Rectangle Fill="#FF646464" Height="2" Margin="10,0" VerticalAlignment="Bottom" />
				<Grid Margin="10" Grid.Row="1" >
					<Grid.ColumnDefinitions>
						<ColumnDefinition Width="200"/>
						<ColumnDefinition Width="0.635*"/>
					</Grid.ColumnDefinitions>
					<ListBox x:Name="myListBox" Margin="10" FontSize="13.333" SelectionMode="Multiple"/>
					<sdk:DataGrid x:Name="myDataGrid" Grid.Column="1" Margin="10" AutoGenerateColumns="True"
							DataContext="{Binding Source={StaticResource SampleDataSource}}"
							ItemsSource="{Binding Collection}" FontSize="13.333"
							AutoGeneratingColumn="myDataGrid_AutoGeneratingColumn">
						<!--
						<sdk:DataGrid.Columns>
							<sdk:DataGridTextColumn Binding="{Binding Property1}" Header="Property1"/>
							<sdk:DataGridCheckBoxColumn Binding="{Binding Property2}" Header="Property2"/>
							<sdk:DataGridTextColumn Binding="{Binding Property3}" Header="Property3"/>
							<sdk:DataGridTextColumn Binding="{Binding Property4}" Header="Property4"/>
							<sdk:DataGridTextColumn Binding="{Binding Property5}" Header="Property5"/>
							<sdk:DataGridTextColumn Binding="{Binding Property6}" Header="Property6"/>
						</sdk:DataGrid.Columns>
						-->
					</sdk:DataGrid>
				</Grid>
				<Button x:Name="myButton" Content="設定顯示欄位" HorizontalAlignment="Center" Grid.Row="3"
						VerticalAlignment="Center" Margin="0,5" Padding="10,5" FontSize="13.333" Click="myButton_Click" />
			</Grid>
		</Border>
	</theme:ExpressionDarkTheme>
</UserControl>

Xaml的部份其實沒什麼特別的地方,除了我在DataGrid上加了一個AutoGeneratingColumn的EventHandler,用來在自動產生欄位的時候,將用來做DataBinding的PropertyName記錄下來。另外,SampleData的部份是透過Expression Blend自動產生的。

 

再來看看Code-Behind的部份:

MainPage.xaml.cs

using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;

namespace SL_DynamicDataGridColumns
{
    public partial class MainPage : UserControl
    {
        private ObservableCollection<string> _columns = new ObservableCollection<string>();

        public MainPage()
        {
            InitializeComponent();

            this.myListBox.ItemsSource = _columns;

            //如果DataGrid的欄位不是自動產生的(AutoGenerateColumns=False),就可以在Loaded事件裡面抓取欄位。但如果是由DataGrid自動產生欄位(AutoGenerateColumns=True),在Loaded中就會抓不到欄位喔!!
            //this.Loaded += new RoutedEventHandler( MainPage_Loaded );
        }

        private void MainPage_Loaded( object sender , RoutedEventArgs e )
        {
            foreach( DataGridColumn dataGridColumn in myDataGrid.Columns )
            {
                if( !_columns.Contains( dataGridColumn.Header.ToString() ) )
                {
                    _columns.Add( dataGridColumn.Header.ToString() );
                }
            }

            this.myListBox.SelectAll();
        }

        private void myButton_Click( object sender , RoutedEventArgs e )
        {
            for( int i = 0 ; i < _columns.Count ; i++ )
            {
                myDataGrid.Columns[ i ].Visibility = Visibility.Collapsed;

                if( ( myListBox.ItemContainerGenerator.ContainerFromIndex( i ) as ListBoxItem ).IsSelected == true )
                {
                    myDataGrid.Columns[ i ].Visibility = Visibility.Visible;
                }
            }
        }

        private void myDataGrid_AutoGeneratingColumn( object sender , DataGridAutoGeneratingColumnEventArgs e )
        {
            if( !_columns.Contains( e.PropertyName ) )
            {
                _columns.Add( e.PropertyName );
            }

            myListBox.SelectAll();
        }
    }
}

 

其實Code-Behind的部份,要完成這樣的功能的方式就有兩種可以選了,得視DataGrid的欄位是否為自動產生的來決定。範例中使用的DataGrid欄位為自動產生,沒辦法在MainWindow的Loaded事件中取得,所以得透過DataGrid的AutoGeneratingColumn事件來幫忙完成取得欄位的動作。

其他的部份就真的都很簡單啦,只要操作DataGridColumn的Visibility屬性,就可以做到顯示/隱藏的切換啦!!

 

以上~

 

最後附上專案原始碼,歡迎自行取用: