下面是一个简单的WPF应用程序,它显示订单最多的客户,它是通过代码隐藏中的LINQ-to-SQL从数据库中收集的。
扩展此WPF应用程序的最佳方法是什么,以便用户可以从下拉列表中进行选择,例如:
将显示相应的集合?
以下是一些想法:
您如何在WPF / Silverlight应用中解决这个常见的业务问题,即客户点击控件和屏幕区域会向他显示相应的信息?
XAML:
<Window x:Class="TestLinqToSql123.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="500">
<Window.Resources>
<DataTemplate x:Key="CustomerTemplate">
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}The customer {0} lives in {1} and has {2} orders.">
<Binding Path="Name"/>
<Binding Path="City"/>
<Binding Path="NumberOfOrders"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</Window.Resources>
<DockPanel>
<Border
Background="Orange"
CornerRadius="5"
Margin="10"
Padding="10">
<ScrollViewer>
<StackPanel>
<TextBlock Text="Customers with the most orders:"
Margin="0 0 0 10"
FontSize="18"/>
<ItemsControl x:Name="TheList"
ItemTemplate="{StaticResource CustomerTemplate}"/>
</StackPanel>
</ScrollViewer>
</Border>
</DockPanel>
</Window>
代码隐藏:
using System.Windows;
using TestLinqToSql123.Models;
using System.Linq;
namespace TestLinqToSql123
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
NorthwindDataContext db = new NorthwindDataContext();
var customers = from c in db.Customers
orderby c.Orders.Count descending
select new
{
Name = c.ContactName,
c.City,
NumberOfOrders = c.Orders.Count
};
TheList.ItemsSource = customers;
}
}
}
答案 0 :(得分:2)
我会使用在WPF和Silverlight应用程序中非常流行的Model-View-ViewModel模式。
客户类是模型中的实体。您还需要一个存储库或服务类,以根据各种条件返回客户集合。在Silverlight中,异步检索数据会使事情变得复杂。通过为此存储库或服务类创建接口或抽象基类,您可以在不使用数据库的情况下测试ViewModel类。您可以改为模拟一些测试数据。
ViewModel使用数据绑定连接到视图,它必须实现INotifyPropertyChanged
和/或INotifyCollectionChanged
或使用依赖项属性公开其数据。前一种方法通常更容易实施和测试。
在您的示例中,您似乎只想使用各种排序条件对相同的集合进行排序。然后,您的ViewModel就是客户对象的集合。显示客户非常简单,ViewModel可以直接包含客户实体对象。在更复杂的场景中,例如在可以编辑客户的地方,您可以创建客户视图模型。
您的ViewModel可以来自ObservableCollection<T>
或CollectionView
。后者是Silverlight中没有的类,您必须通过实现ICollectionView
来实现自己的类。
除了作为客户对象的集合之外,ViewModel还需要一些方法来确定要使用的排序顺序。实际上,向ViewModel添加SortOrder
属性并在此属性更改时求助于集合可能更为明智。
重要的一点是ViewModel不了解用户界面,可以独立于用户界面进行测试。
视图是UserControl
,使用XAML实现。有些人发现在View中根本没有代码隐藏非常重要,但Silverlight中缺少命令需要一些代码隐藏或一些类似命令的附加属性(PRISM在Silverlight中支持这一点)。
View的DataContext
设置为ViewModel,然后使用数据绑定将View的元素绑定到ViewModel的各个部分。按钮和其他活动用户界面控件连接到ViewModel上的方法等。在WPF中,您可以使用命令,但在Silverlight中,您需要一些代码隐藏或与命令类似的东西。
当用户单击View中的控件时,操作将作为方法调用或属性更改路由到ViewModel。然后更新ViewModel,从View到ViewModel的数据绑定可确保向用户显示更新的信息。
答案 1 :(得分:1)
您可以非常轻松地在简单的代码隐藏中执行此操作。在边框上方添加以下组合。
<ComboBox
x:Name="SelectionCombo"
DockPanel.Dock="Top"
SelectionChanged="ComboBox_SelectionChanged"
>
<ComboBoxItem x:Name="MostOrders">Customers with the most orders</ComboBoxItem>
<ComboBoxItem x:Name="LeastOrders">Customers with the least orders</ComboBoxItem>
<ComboBoxItem x:Name="ByCity">Customers by city</ComboBoxItem>
<ComboBoxItem x:Name="ByState">Customers by state</ComboBoxItem>
</ComboBox>
然后在你的代码后面添加以下事件处理程序
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBoxItem item = (ComboBoxItem)e.AddedItems[0];
if (item == MostOrders)
GetByMostOrders();
else if (item == LeastOrders)
GetByLeastOrders();
else if (item == ByCity)
GetByCity();
else if (item == ByState)
GetByState();
}
然后创建填充组合的方法
private void GetByMostOrders()
{
NorthwindDataContext db = new NorthwindDataContext();
var customers = from c in db.Customers
orderby c.Orders.Count descending
select new
{
Name = c.ContactName,
c.City,
NumberOfOrders = c.Orders.Count
};
TheList.ItemsSource = customers;
}
如果您正在寻找更复杂的方法,我可能会遵循马丁的建议,否则这应该可以让您入手。