定义数据类型
1 public enum OrderSource
2 {
3 Phone,
4 Internet,
5 WalkIn,
6 Fax,
7 }
8
9 public struct PizzaOrder
10 {
11 public OrderSource Source {get;set; }
12 public string PhoneNumber { get; set; }
13 public int Size { get; set; }
14 public bool IsDelivery { get; set; }
15 public PizzaToppings[] Toppings { get; set; }
16 }
定义模板
1 <Application x:Class="AcmePizza.App"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:local="clr-namespace:AcmePizza"
5 StartupUri="Window1.xaml">
6 <Application.Resources>
7 <!--A reusable data template when binding to a collection of pizza orders. this template is used in both the main window and
8 current order window, where it is scaled larger-->
9 <DataTemplate x:Key="PizzaOrderTemplate">
10 <Canvas Width="200" Height="200">
11 <Rectangle x:Name="orderRectangle" RadiusX="6" RadiusY="6" Width="200" Height="200" Fill="LightBlue" Opacity="60"/>
12 <TextBlock Margin="10,10,0,0" Text="Phone:"/>
13 <TextBlock Margin="50,10,0,0" FontWeight="Bold" Text="{Binding Path=PhoneNumber}"/>
14 <local:PizzaSizeCircle x:Name="pizzaSize" Canvas.Right="5" Canvas.Bottom="5" PizzaSize="17"/>
15 <Image x:Name="sourceIcon" Source="phonesource.ico" Canvas.Left="5" Canvas.Bottom="5"/>
16 <ItemsControl Canvas.Top="40" Canvas.Left="30" ItemsSource="{Binding Path=Toppings}"/>
17 </Canvas>
18 <DataTemplate.Triggers>
19 <DataTrigger Binding="{Binding Path=IsDelivery}" Value="true">
20 <DataTrigger.Setters>
21 <Setter Property="Fill" TargetName="orderRectangle" Value="Pink"/>
22 </DataTrigger.Setters>
23 </DataTrigger>
24 <DataTrigger Binding="{Binding Path=Size}" Value="11">
25 <DataTrigger.Setters>
26 <Setter Property="PizzaSize" TargetName="pizzaSize" Value="11"/>
27 </DataTrigger.Setters>
28 </DataTrigger>
29 <DataTrigger Binding="{Binding Path=Size}" Value="13">
30 <DataTrigger.Setters>
31 <Setter Property="PizzaSize" TargetName="pizzaSize" Value="13"/>
32 </DataTrigger.Setters>
33 </DataTrigger>
34 <DataTrigger Binding="{Binding Path=Source}" Value="{x:Static Member=local:OrderSource.Internet}">
35 <Setter Property="Source" TargetName="sourceIcon" Value="internetsource.ico"/>
36 </DataTrigger>
37 <DataTrigger Binding="{Binding Path=Source}" Value="{x:Static Member=local:OrderSource.Phone}">
38 <Setter Property="Source" TargetName="sourceIcon" Value="phonesource.ico"/>
39 </DataTrigger>
40 <DataTrigger Binding="{Binding Path=Source}" Value="{x:Static Member=local:OrderSource.Fax}">
41 <Setter Property="Source" TargetName="sourceIcon" Value="faxsource.ico"/>
42 </DataTrigger>
43 <DataTrigger Binding="{Binding Path=Source}" Value="{x:Static Member=local:OrderSource.WalkIn}">
44 <Setter Property="Source" TargetName="sourceIcon" Value="walkinsource.ico"/>
45 </DataTrigger>
46 </DataTemplate.Triggers>
47 </DataTemplate>
48 </Application.Resources>
49 </Application>
使用模板
1 <Window x:Class="AcmePizza.Window1"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:local="clr-namespace:AcmePizza"
5 Title="Acme Pizza Co. - Current Orders" Height="428" Width="1038"
6 Loaded="Window_Loaded" WindowState="Maximized" WindowStartupLocation="CenterScreen" ResizeMode="CanResize"
7 >
8 <Grid>
9 <Grid.RowDefinitions>
10 <RowDefinition Height="55"/>
11 <RowDefinition Height="243*"/>
12 </Grid.RowDefinitions>
13 <Grid.ColumnDefinitions>
14 <ColumnDefinition Width="539"/>
15 <ColumnDefinition Width="477*" />
16 </Grid.ColumnDefinitions>
17
18 <ItemsControl x:Name="ordersList" ItemsSource="{Binding}" ItemTemplate="{StaticResource PizzaOrderTemplate}"
19 Grid.Row="1" Grid.ColumnSpan="2" VerticalAlignment="Top" Margin="0,0,0,0">
20 <ItemsControl.ItemsPanel>
21 <ItemsPanelTemplate>
22 <WrapPanel/>
23 </ItemsPanelTemplate>
24 </ItemsControl.ItemsPanel>
25 <ItemsControl.ItemContainerStyle>
26 <Style>
27 <Setter Property="Control.Width" Value="205"/>
28 <Setter Property="Control.Height" Value="205"/>
29 <Setter Property="Control.Margin" Value="2.5"/>
30 </Style>
31 </ItemsControl.ItemContainerStyle>
32 </ItemsControl>
33 <TextBlock Height="59" Name="textBlock1" VerticalAlignment="Top" Text="Acme Pizza Co." Foreground="Coral" FontSize="38" Margin="10,0,202,0" />
34 <TextBlock FontSize="38" Foreground="LightGreen" TextAlignment="Right" Name="textBlock2" Text="Current Orders" Margin="198,0,0,0" Grid.Column="1" />
35 <Image Height="55" Margin="0,4,201,0"
36 Name="image1" Stretch="UniformToFill" VerticalAlignment="Top" Source="pizzaicon.png" HorizontalAlignment="Right" Width="62" />
37 <Button Name="processNextOrderButton" Click="processNextOrderButton_Click" Margin="0,13,0,12" HorizontalAlignment="Right" Width="164">Process Next Order</Button>
38 </Grid>
39 </Window>
绑定数据源
1 public partial class Window1 : Window
2 {
3 private IProducerConsumerCollection<PizzaOrder> m_orders;
4 private static Random m_rand = new ThreadSafeRandom();
5
6 public Window1()
7 {
8 InitializeComponent();
9
10 // intialize the bindable collection and set it as the data context
11 var orders = new ObservableConcurrentCollection<PizzaOrder>();
12 // store the observable collection as an explicity producer consumer
13 // collection that has tryadd and tryremove operations
14 m_orders = orders;
15 // set the AcmePizza as the defaut
16 this.DataContext = orders;
17 }
18
19 private void Window_Loaded(object sender, EventArgs e)
20 {
21 // launch four threads that mimic various sources
22 Task.Factory.StartNew(() => { OrdererThread(OrderSource.Fax); }, TaskCreationOptions.AttachedToParent);
23 Task.Factory.StartNew(() => { OrdererThread(OrderSource.Internet); }, TaskCreationOptions.AttachedToParent);
24 Task.Factory.StartNew(() => { OrdererThread(OrderSource.Phone); }, TaskCreationOptions.AttachedToParent);
25 Task.Factory.StartNew(() => { OrdererThread(OrderSource.WalkIn); }, TaskCreationOptions.AttachedToParent);
26 }
27
28 private void OrdererThread(OrderSource source)
29 {
30 for ( int i = 0; i < 10; ++i )
31 {
32 // submit random order
33 m_orders.TryAdd( GenerateRandomOrder(source));
34 // sleep for a random period
35 Thread.Sleep(m_rand.Next(1000, 4001));
36 }
37 }
38
39 private static PizzaOrder GenerateRandomOrder(OrderSource source)
40 {
41 // source
42 var order = new PizzaOrder { Source = source };
43 // delivery
44 order.IsDelivery = m_rand.Next(0, 2) == 0 ? true : false;
45 // phone number
46 var areaCode = m_rand.Next(0, 2) == 0 ? 425 : 206;
47 var firstThreeDigits = m_rand.Next(100, 1000);
48 var lastFourDigits = m_rand.Next(0, 10000);
49 order.PhoneNumber = String.Format("({0}) {1}-{2}", areaCode, firstThreeDigits, lastFourDigits.ToString("D4"));
50 // size
51 switch (m_rand.Next(0, 3))
52 {
53 case 0: order.Size = 11; break;
54 case 1: order.Size = 13; break;
55 case 2: order.Size = 17; break;
56 }
57 // toppings
58 var availToppings = new List<PizzaToppings>(Enum.GetValues(typeof(PizzaToppings)).Cast<PizzaToppings>());
59 order.Toppings = new PizzaToppings[m_rand.Next(1, 5)];
60 for (int j = 0; j < order.Toppings.Length; ++j)
61 {
62 var toppingIndex = m_rand.Next(0, availToppings.Count);
63 order.Toppings[j] = availToppings[toppingIndex];
64 availToppings.RemoveAt(toppingIndex);
65 }
66 return order;
67 }
68
69 private void processNextOrderButton_Click(object sender, RoutedEventArgs e)
70 {
71 // attempt to get an order from the queue
72 PizzaOrder nextOrder;
73 if ( !m_orders.TryTake( out nextOrder ) )
74 {
75 MessageBox.Show( "No orders available. Please try again later.");
76 return;
77 }
78 // if successful launch an order window
79 var currentOrderWindow = new CurrentOrderWindow(nextOrder);
80 currentOrderWindow.Show();
81 }
82 }
浙公网安备 33010602011771号