Silverlight DataGrid 中的运行时条件控件






4.93/5 (5投票s)
Silverlight DataGrid 中的运行时条件控件
引言
大多数业务应用程序会在 Silverlight 中实现 DataGrid
,而每种场景都有其自身的复杂性,有时看起来有趣但又充满挑战。我写这篇文章是因为遇到了一个类似的情况。在这篇文章中,我们将使用 IValueConverter
并结合一些常识,讨论在 DataGrid
中将各种控件绑定到特定列的不同单元格的方法。
问题/场景
我们的应用程序需要将一些记录显示在网格中……这是我们即使睡着也能做到的最简单的事情。但挑战在于根据业务规则显示不同的控件集。让我举个例子来说明。
我们有一组 Customer
列表需要在 Grid
中显示。Customer
对象包含一个名为 Mood
的属性,该属性可以是 Happy
、Neutral
或 Angry
。好吧,这还没完。如果 Mood
不可用,单元格必须显示“NA”;如果属性为 null
,则应显示一个 HyperlinkButton
,该按钮将向特定客户发送请求以征求反馈。下面可以看到特定控件的原型
因此,网格必须足够智能,能够根据需要在运行时使用 Image 控件、简单的 TextBlock 控件(显示 NA)或具有自定义代码后置逻辑的 Button 控件。每行的绑定数据将决定特定列的控件。我的下一节将重点介绍不同的方法和一些 DataGrid 自定义的で基本概念。
解决问题和 DataGrid 的一些基础知识
DataGrid
提供了多种列类型,可以是:
DataGridTextColumn
:用于纯文本值DataGridCheckBoxColumn
:用于布尔值DataGridTemplateColumn
:用于集成控件(绑定控件)
有关这些列类型及其使用场景的简要说明,请在此处 很好地描述。一旦我们选择自定义的 ColumnType
,我们就可以使用任何控件作为单元格模板来容纳绑定数据。要使用自定义列,我们应该强制 DataGrid
停止自动生成列,而是定义我们自己的列并分配绑定属性。下图显示了一个带有自定义列的 DataGrid
。
DataGridTemplateColumn
方便显示带有用于编辑的绑定控件的自定义列内容。默认情况下,它支持在列单元格中使用统一的控件。这意味着一旦定义,该列的所有单元格都将是统一的。如前所述,DataGrid
的 CellTemplate
属性允许我们在单元格处于非编辑模式时显示数据。
在这篇文章中,我们将重点关注数据的显示,因此我们的重点将放在 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>
考虑最后一列
这里的 Converter
作为资源的控件添加,它将定义 UIElement
,然后该 UIElement
将用于显示值。下一步是为 Mood
显示创建一个 Converter
。Converter
是允许你在控件进行绑定过程时修改数据的方法。Converter
方法继承自 IValueConverter,并实现 Convert
和 ConvertBack
方法来修改源到目标以及反之。有关此主题的更多详细信息可以在此处找到 找到。
此特定项目的 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
正是我们需要的
最后的话…
以上工作是 DataGrid
自定义的一个示例。CellTemplate
结合 DataGridTemplateColumn
可用于进一步的自定义。希望这篇文章能帮助你理解 Grid
的概念和自定义概念。Silverlight 提供的灵活性令人惊叹,XAML 绝对值得成为 Microsoft 的焦点。请告诉我你的看法 。