65.9K
CodeProject 正在变化。 阅读更多。
Home

Silverlight DataGrid 中的运行时条件控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.93/5 (5投票s)

2011 年 8 月 9 日

CPOL

4分钟阅读

viewsIcon

33389

downloadIcon

761

Silverlight DataGrid 中的运行时条件控件

引言

大多数业务应用程序会在 Silverlight 中实现 DataGrid,而每种场景都有其自身的复杂性,有时看起来有趣但又充满挑战。我写这篇文章是因为遇到了一个类似的情况。在这篇文章中,我们将使用 IValueConverter 并结合一些常识,讨论在 DataGrid 中将各种控件绑定到特定列的不同单元格的方法。

问题/场景

我们的应用程序需要将一些记录显示在网格中……这是我们即使睡着也能做到的最简单的事情。但挑战在于根据业务规则显示不同的控件集。让我举个例子来说明。

我们有一组 Customer 列表需要在 Grid 中显示。Customer 对象包含一个名为 Mood 的属性,该属性可以是 HappyNeutralAngry。好吧,这还没完。如果 Mood 不可用,单元格必须显示“NA”;如果属性为 null,则应显示一个 HyperlinkButton,该按钮将向特定客户发送请求以征求反馈。下面可以看到特定控件的原型

SNAGHTMLcefdd2_thumb1.png

因此,网格必须足够智能,能够根据需要在运行时使用 Image 控件、简单的 TextBlock 控件(显示 NA)或具有自定义代码后置逻辑的 Button 控件。每行的绑定数据将决定特定列的控件。我的下一节将重点介绍不同的方法和一些 DataGrid 自定义的で基本概念。

解决问题和 DataGrid 的一些基础知识

DataGrid 提供了多种列类型,可以是:

  1. DataGridTextColumn:用于纯文本值
  2. DataGridCheckBoxColumn:用于布尔值
  3. DataGridTemplateColumn:用于集成控件(绑定控件)

有关这些列类型及其使用场景的简要说明,请在此处 很好地描述。一旦我们选择自定义的 ColumnType,我们就可以使用任何控件作为单元格模板来容纳绑定数据。要使用自定义列,我们应该强制 DataGrid 停止自动生成列,而是定义我们自己的列并分配绑定属性。下图显示了一个带有自定义列的 DataGrid

image_thumb2.png

DataGridTemplateColumn 方便显示带有用于编辑的绑定控件的自定义列内容。默认情况下,它支持在列单元格中使用统一的控件。这意味着一旦定义,该列的所有单元格都将是统一的。如前所述,DataGridCellTemplate 属性允许我们在单元格处于非编辑模式时显示数据。

SNAGHTML3846440_thumb3.png

在这篇文章中,我们将重点关注数据的显示,因此我们的重点将放在 CellTemplate 上。

在寻找上述问题的解决方案时,我们考虑了各种选项,例如动态 DataTemplate(DataTemplateSelector),WPF 支持但 Silverlight 不支持。DataTemplateSelector 允许根据数据对象逻辑使用特定的模板。然后,我考虑在运行时修改 XAML,在代码后置中创建 DataTemplate 并将其附加到单元格模板,尽管我们将其保留为最后的选择。我们正在寻找一个控件,它可以容纳在运行时定义的任何控件,并且控件的选择可以通过 IValueConverter 根据特定的业务对象来决定。

关于 ContentControl 呢?基本上 ContentControl 是一个控件,其 Content 属性可以是任何 Silverlight UIElement

因此,对于给定的场景,最佳解决方案是在 DataTemplate 中使用 ContentControl,并通过 IValueConverter 在运行时分配所需的自定义控件。我们将在下一节中介绍实现。

设置 Grid 和绑定

页面包含一个 Grid,它将显示 Customer 数据。Customer 业务实体对象定义如下:

namespace GridInSilverlight 
{ 
  public  enum Mood
    {
        NA,
        Satisfied,
        Normal,
        UnSatisfied,
        UA
    }
  
    public class Customer
   {
        public string Name{get;set;}
        public string Place { get; set; }
        public string  Phone{get;set;}
        public bool IsCorporate{get;set;}
        public Mood CustomerMood { get; set; }
    }
}

以及上述实体的 Grid 定义如下:

<sdk:DataGrid AutoGenerateColumns="False" 
                      Height="253"
                      Margin="12,45,0,0"
                      Name="dgCustomers"
                      VerticalAlignment="Top"
                      HorizontalAlignment="Left"
                      Width="462">
    <sdk:DataGrid.Columns>
        <sdk:DataGridTextColumn CanUserReorder="True"
                                   CanUserResize="True"
                                   CanUserSort="True"
                                   Width="Auto" 
                                   Binding="{Binding Name}" Header="Name"/>
        <sdk:DataGridTextColumn CanUserReorder="True"
                                   CanUserResize="True"
                                   CanUserSort="True"
                                   Width="Auto"
                                   Binding="{Binding Place}"
                                   Header="Country" />
        <sdk:DataGridTextColumn CanUserReorder="True"
                                   CanUserResize="True"
                                   CanUserSort="True"
                                   Width="Auto"
                                   Binding="{Binding Phone}"
                                   Header="Phone" />
        <sdk:DataGridCheckBoxColumn 
                                   Width="Auto"
                                   Binding="{Binding IsCorporate}"
                                   Header="Is Corporate" />
        <sdk:DataGridTemplateColumn CanUserReorder="True"
                                   CanUserResize="True"
                                   CanUserSort="True"
                                   Width="Auto"  Header="Mood">
            <sdk:DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ContentControl Content=
				"{Binding Converter={StaticResource MoodConv },
			         ConverterParameter='CUS'}"
                                    HorizontalContentAlignment="Stretch"
                                    VerticalContentAlignment="Stretch" /> 
                        </DataTemplate>
                        
            </sdk:DataGridTemplateColumn.CellTemplate>
        </sdk:DataGridTemplateColumn>
        <sdk:DataGridTemplateColumn CanUserReorder="True"
                                    CanUserResize="True"
                                    CanUserSort="True"
                                    Width="Auto"
                                    Header="Company Mood">
            <sdk:DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ContentControl Content="{Binding Converter=
				{StaticResource MoodConv },ConverterParameter='COM'}"
                                     HorizontalContentAlignment="Stretch"
                                     VerticalContentAlignment="Stretch" />
                </DataTemplate>
            </sdk:DataGridTemplateColumn.CellTemplate>
        </sdk:DataGridTemplateColumn>
    </sdk:DataGrid.Columns>
</sdk:DataGrid>  

考虑最后一列

SNAGHTML3846440_thumb4.png

这里的 Converter 作为资源的控件添加,它将定义 UIElement,然后该 UIElement 将用于显示值。下一步是为 Mood 显示创建一个 ConverterConverter 是允许你在控件进行绑定过程时修改数据的方法。Converter 方法继承自 IValueConverter,并实现 ConvertConvertBack 方法来修改源到目标以及反之。有关此主题的更多详细信息可以在此处找到 找到

此特定项目的 Converter 代码是:

public class MoodConvertor:IValueConverter
   {
       #region IValueConverter Members
 
       public object Convert(object value, Type targetType, 
		object parameter, System.Globalization.CultureInfo culture)
       { 
           Customer cusObj = value as Customer;
           Image img = new Image();
           switch (cusObj.CustomerMood)
           { 
               case Mood.Normal:
 
                       img.Source = new System.Windows.Media.Imaging.BitmapImage
					(new Uri("Normal.png", UriKind.Relative));
                   return img;
 
               case Mood.Satisfied:
 
                   img.Source = new System.Windows.Media.Imaging.BitmapImage
				(new Uri("Satisfied.png", UriKind.Relative));
                   return img;
 
               case Mood.UnSatisfied:
                   img.Source = new System.Windows.Media.Imaging.BitmapImage
				(new Uri("UnSatisfied.png", UriKind.Relative));
                   return img;
 
               case Mood.UA:
                   HyperlinkButton btn = new HyperlinkButton();
                   btn.Content = "Invite Suggestion";
                   return btn;
 
               default :
                   TextBlock tbU = new TextBlock();
                   tbU.Text = "-";
                   return tbU;
           } 
       }
 
       public object ConvertBack(object value, Type targetType, 
		object parameter, System.Globalization.CultureInfo culture)
       {
           throw new NotImplementedException();
       }
 
       #endregion
   } 

几行代码生成了虚拟客户数据,在你的情况下,可以是来自你的服务调用的数据。编译项目后,Grid 正是我们需要的

Dynamic Control for DataGrid

最后的话…

以上工作是 DataGrid 自定义的一个示例。CellTemplate 结合 DataGridTemplateColumn 可用于进一步的自定义。希望这篇文章能帮助你理解 Grid 的概念和自定义概念。Silverlight 提供的灵活性令人惊叹,XAML 绝对值得成为 Microsoft 的焦点。请告诉我你的看法 马上回来

© . All rights reserved.