Script that approximates what I did in my talk...
Make sure you also look at About This Demo
Will post the files to add to the project soon. (having upload problems)
VS
====
Create a C# Avalon App project named Lap
Aurora
===========
Open window1.xaml in VS by choosing Open With...Aurora.
Before adding the Image
In VS, Create Images folder in project
Also add existing item/contoso.png and iconMain.ico
Set app icon
==========
Right click on Lap Project in solution explorer...properties
Set Resources/Icon to Images\iconMain.ico
Window1.xaml
===========
[in the demo, I copied and pasted this on top of what I built in Aurora so that the persisted xaml was "clean".]
<Window xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"
x:Class="Lap.Window1"
Title="Lap"
>
<Grid Name="rootPanel">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button Grid.Column="0" FontStyle="Normal"
Margin="5,5,5,5"
Name="Button1" Grid.Row="2">
Add New Patient
</Button>
<ListBox Grid.Column="0" FontFamily="Tahoma"
Name="ListBox1" Grid.Row="1">
<ListBoxItem>
ListBoxItem1
</ListBoxItem>
<ListBoxItem>
ListBoxItem2
</ListBoxItem>
<ListBoxItem>
ListBoxItem3
</ListBoxItem>
<ListBoxItem>
ListBoxItem4
</ListBoxItem>
<ListBoxItem>
ListBoxItem5
</ListBoxItem>
</ListBox>
<Image Source="Images/contoso.png" />
<Slider
Name="Slider1"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Minimum=".1"
Maximum=".4"
Value=".2"
SmallChange=".05"
/>
</Grid>
</Window>
Scaling handlers
===========
double zoomFactor;
double smallestDimensionInInches;
private void zoomLevelChanged(object sender,
RoutedEventArgs e)
{
zoomFactor = Slider1.Value;
ScaleContent();
}
private void windowResized(object sender,
SizeChangedEventArgs e)
{
const double inch = 96;
smallestDimensionInInches =
Math.Min(this.ActualHeight,
this.ActualWidth)
/ inch;
ScaleContent();
}
private void ScaleContent()
{
double scale =
smallestDimensionInInches * zoomFactor;
if (scale == 0.0)
return;
rootPanel.LayoutTransform =
new ScaleTransform(scale, scale);
Slider1.LayoutTransform =
new ScaleTransform(1 / scale, 1 / scale);
}
Add handlers to .xaml file:
================
Add SizeChanged="windowResized" to <Window>
Add ValueChanged="zoomLevelChanged" to <Slider>
Patient DataModel
===========
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Media;
namespace Lap
{
internal class Patient
{
public Patient()
{
}
private string myLastName;
public string LastName
{
get { return myLastName; }
set { myLastName = value; }
}
private string myFirstName;
public string FirstName
{
get { return myFirstName; }
set { myFirstName = value; }
}
private string myAgeSex;
public string AgeSex
{
get { return myAgeSex; }
set { myAgeSex = value; }
}
private string myRoomNumber;
public string RoomNumber
{
get { return myRoomNumber; }
set { myRoomNumber = value; }
}
private string myDiagnosis;
public string Diagnosis
{
get { return myDiagnosis; }
set { myDiagnosis = value; }
}
public string FullName
{
get
{
return LastName + ", " + FirstName;
}
}
private bool myAutoGenerate;
public bool AutoGenerate
{
get { return myAutoGenerate; }
set
{
myAutoGenerate = value;
if (myAutoGenerate == true)
AutoGenerateProperties();
}
}
static string[] firstNames =
new string[] { "Bernice", "Arthur", "Miriam", "Frank", "Anne", "Richard",
"Grace", "Robert", };
static string[] lastNames =
new string[] { "Flemming", "Naegele", "Marthens", "Spring", "Gawalek",
"Young", "Arengo", "Relyea" };
static string[] diagnoses =
new string[] { "Markup-itis", "Code-itis", "Design-itis" };
static char[] sexes =
new char[] { 'F', 'M', 'F', 'M', 'F', 'M', 'F', 'M' };
static string[] photos =
new string[] { "bf.jpg", "an.jpg", "mm.jpg", "fs.jpg", "ag.jpg", "ry.jpg",
"ga.jpg", "rr.jpg" };
static Random random;
static int personIndex = 0;
public void AutoGenerateProperties()
{
if (random == null)
random = new Random();
FirstName =
firstNames[personIndex];
LastName =
lastNames[personIndex];
char sex = sexes[personIndex];
AgeSex =
sex + (random.Next(20) + 60).ToString();
RoomNumber =
(1000 * random.Next(4) + random.Next(500)).ToString();
Diagnosis =
diagnoses[random.Next(diagnoses.Length)];
if (personIndex == firstNames.Length - 1)
personIndex = 0;
else
personIndex++;
}
}
}
use my:Patient, mappingPI, DisplayMemberPath
============================================
At root: <?Mapping XmlNamespace="myapp" ClrNamespace="Lap" ?>
In window, add xmlns:my="myapp"
Replace ListBoxItems with data inside the listbox:
<my:Patient FirstName="Rob" LastName="Relyea" AgeSex="M35"
RoomNumber="2534" />
<my:Patient AutoGenerate="True" />
<my:Patient AutoGenerate="True" />
<my:Patient AutoGenerate="True" />
<my:Patient AutoGenerate="True" />
<my:Patient AutoGenerate="True" />
<my:Patient AutoGenerate="True" />
Add DisplayMemberPath="FullName" to ListBox
AddNewPatient
===========
void addNewPatient(object sender,
EventArgs e)
{
Patient patientToAdd = new Patient();
patientToAdd.AutoGenerateProperties();
ListBox1.Items.Add(patientToAdd);
}
Wire Button Click Handler
============
Add Click="addNewPatient" to Button
Win BG + Grid Margin
===========
Add Background="Black" to Window
Add Margin="4" to Grid
<Rectangle ... />
===========
Add this element as the first child of the grid.
<Rectangle RadiusX="15"
RadiusY="15"
Grid.RowSpan="3"
Fill="#bbbbbb"
/>
<LinearGradientBrush ... />
===========
Add this element to a new Window.Resources element (which should be the first child
of Window)
<LinearGradientBrush x:Key="niceGradient" >
<LinearGradientBrush.GradientStops>
<GradientStop Color="#ffffcc"
Offset="0" />
<GradientStop Color="#aaaa99"
Offset=".7" />
<GradientStop Color="#ccccaa"
Offset=".75" />
<GradientStop Color="#ccccaa"
Offset=".8" />
<GradientStop Color="#ffffcc"
Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
reference the resource
===
Change Fill on Rectangle to: Fill="{StaticResource niceGradient}"
<Style> for ListBox
===========
<Style TargetType="{x:Type ListBox}">
<Setter Property="Background"
Value="Transparent" />
<Setter Property="FontSize"
Value="14pt" />
<Setter Property="BorderThickness"
Value="0" />
</Style>
in patient.cs, use snippet to add Photo property
======
(prop-tab-tab ImageSource, myPhoto, Photo)
===========
private ImageSource myPhoto;
public ImageSource Photo
{
get { return myPhoto; }
set { myPhoto = value; }
}
AutoGenerate for Photo
===========
After:
Diagnosis =
diagnoses[random.Next(diagnoses.Length)];
Add this:
ImageSourceConverter isc = new ImageSourceConverter();
Photo =
isc.ConvertFromString(
"patientPhotos\\" + photos[personIndex]) as ImageSource;
[NOTE: need to figure out how to avoid having to make the images all "Content"]
Create PatientPhotos\ - "Content"
===========
Add Existing Items (*.jpg from PatientPhotos) and set the Copy to Output Directory to
Copy if newer
<DataTemplate ... /> (and remove DisplayMemberPath)
===========
<DataTemplate DataType="{x:Type my:Patient}">
<Border CornerRadius="35"
Background="{Binding
Path=Background,RelativeSource=/ContentControl}"
Grid.RowSpan="2"
Grid.ColumnSpan="3"
Margin="1"
Name="rootBorder"
>
<Grid Margin="7,10" >
<Image Width="51"
Height="71"
Grid.RowSpan="2"
Stretch="Fill"
Source="{Binding Photo}"
Grid.Column="0"
>
<Image.Clip>
<EllipseGeometry
RadiusX="25"
RadiusY="35"
Center="25,35"/>
</Image.Clip>
</Image>
<TextBlock
Text="{Binding
FirstName}"
Grid.Column="1"
Grid.ColumnSpan="3"
FontSize="36"
Margin="5,0,0,0"
/>
<TextBlock
Text="{Binding
LastName}"
Grid.Column="1"
Grid.Row="1"
FontSize="12"
Margin="8,0,0,0"
/>
<TextBlock
Grid.Row="1"
Grid.Column="2"
Grid.ColumnSpan="2"
FontFamily="Segoe UI"
FontSize="12"
TextAlignment="Right"
Text="{Binding
RoomNumber}"
Margin="0,0,20,0"
/>
<ColumnDefinition
Width="60"/>
<ColumnDefinition
Width="*"/>
<ColumnDefinition
Width="20"/>
<ColumnDefinition
Width="40"/>
<RowDefinition
Height="2*"/>
<RowDefinition
Height="1*"/>
</Grid>
</Border>
</DataTemplate>
<Style> for ListBoxItem
===========
<Style TargetType="{x:Type ListBoxItem}">
<Setter
Property="Background"
Value="#ccffffff" />
<Style.Triggers>
<Trigger
Property="IsSelected"
Value="True">
<Setter
Property="Foreground"
Value="RoyalBlue" />
<Setter
Property="Background"
Value="#cc99ccff" />
</Trigger>
</Style.Triggers>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate
TargetType="{x:Type ListBoxItem}">
<ContentPresenter
HorizontalAlignment="Stretch" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Add new column to grid...Width="3*"
===
<my:PatientDetail ... />
===========
Add this element as a child of Grid.
<my:PatientDetail
x:Name="patientDetail1"
Grid.Column="1"
Grid.RowSpan="3"
/>
<GridSplitter ... />
===========
<GridSplitter ResizeDirection="Columns"
Grid.RowSpan="3"/>
Add reference to ChartFx control.
=====
Make Listbox select the first item
===========
SelectedIndex="0"
Bind DataContext to SelectedItem
===========
On the PatientDetail element, set DataContext="{Binding
Path=SelectedItem,ElementName=ListBox1}"
Add Existing Dictionaries
==================
Create Folder Dictionaries
Import existing vectors.xaml
ContosoLogo
==================
Add The following inside myapp.xaml's Application.Resources:
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="Dictionaries/vectors.xaml" />"
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Replace <Image /> with
===================
<StaticResource ResourceKey="ContosoLogo" />
Diagnoses\
===========
UserControl walkthrough
===========
[consider going into some of the code in the usercontrol if appropriate]
Other Ideas to consider
====================
create hyperlink to metro document
export vectors from acrylic
Windows and WPF give you the power to build:
=====================================
Richly Functioned, Well Designed, Data Driven & Connected*,
Resolution Independant, Accessible, Globalized,
AutoUpdating