1
0
mirror of synced 2024-11-25 04:03:08 +01:00

Mostly layout work

This commit is contained in:
PsychoMark 2016-06-18 20:30:12 +02:00
parent f87b023552
commit 9a864f14f1
18 changed files with 647 additions and 155 deletions

View File

@ -1,4 +1,12 @@
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="PettingZoo.App"
Startup="ApplicationStartup">
<Application.Resources> <Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Style.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources> </Application.Resources>
</Application> </Application>

View File

@ -1,8 +1,44 @@
using System.Windows; using System.Linq;
using System.Reflection;
using System.Windows;
using PettingZoo.Model;
using PettingZoo.View;
using SimpleInjector;
namespace PettingZoo namespace PettingZoo
{ {
public partial class App : Application public partial class App : Application
{ {
public void ApplicationStartup(object sender, StartupEventArgs e)
{
var container = Bootstrap();
RunApplication(container);
}
private static Container Bootstrap()
{
var container = new Container();
container.Register<IConnectionFactory, RabbitMQClientConnectionFactory>();
container.Register<IConnectionInfoBuilder, WindowConnectionInfoBuilder>();
// Automatically register all Window and BaseViewModel descendants
foreach (var type in Assembly.GetExecutingAssembly().GetExportedTypes()
.Where(t => t.IsSubclassOf(typeof(System.Windows.Window)) ||
t.IsSubclassOf(typeof(Infrastructure.BaseViewModel))))
{
container.Register(type);
}
return container;
}
private static void RunApplication(Container container)
{
var mainWindow = container.GetInstance<MainWindow>();
mainWindow.Show();
}
} }
} }

View File

@ -0,0 +1,101 @@
using System.Windows;
using System.Windows.Controls;
namespace PettingZoo.Infrastructure
{
// Source: http://daniel-albuschat.blogspot.nl/2011/07/gridlayout-for-wpf-escape-margin-hell.html
// The GridLayout is a special Panel that can be used exactly like the Grid Panel, except that it
// defines a new property ChildMargin. ChildMargin's left, top, right and bottom margins will be applied
// to all children in a way that the children will have a vertical space of ChildMargin.Top+ChildMargin.Bottom
// and a horizontal space of ChildMargin.Left+ChildMargin.Right between them.
// However, there is no margin for the borders of the internal widget, so that the GridLayout itself can be
// aligned to another element without a margin.
// It's best to have a look at TestWindow, which effectively tests all possible alignments of children.
public class GridLayout : Grid
{
public static readonly DependencyProperty ChildMarginProperty = DependencyProperty.Register(
"ChildMargin",
typeof (Thickness),
typeof (GridLayout),
new FrameworkPropertyMetadata(new Thickness(5))
{
AffectsArrange = true,
AffectsMeasure = true
});
// The child margin defines a margin that will be automatically applied to all children of this Grid.
// However, the children at the edges will have the respective margins remove. E.g. the leftmost children will have
// a Margin.Left of 0 and the children in the first row will have a Margin.Top of 0.
// The margins that are not set to 0 are set to half the ChildMargin's value, since it's neighbour will also apply it,
// effectively doubling it.
public Thickness ChildMargin
{
get { return (Thickness) GetValue(ChildMarginProperty); }
set
{
SetValue(ChildMarginProperty, value);
UpdateChildMargins();
}
}
// UpdateChildMargin first finds out what's the rightmost column and bottom row and then applies
// the correct margins to all children.
public void UpdateChildMargins()
{
int maxColumn = 0;
int maxRow = 0;
foreach (UIElement element in InternalChildren)
{
int row = GetRow(element);
int column = GetColumn(element);
if (row > maxRow)
maxRow = row;
if (column > maxColumn)
maxColumn = column;
}
foreach (UIElement element in InternalChildren)
{
FrameworkElement fe = element as FrameworkElement;
if (null != fe)
{
int row = GetRow(fe);
int column = GetColumn(fe);
double factorLeft = 0.5;
double factorTop = 0.5;
double factorRight = 0.5;
double factorBottom = 0.5;
// Top row - no top margin
if (row == 0)
factorTop = 0;
// Bottom row - no bottom margin
if (row == maxRow)
factorBottom = 0;
// Leftmost column = no left margin
if (column == 0)
factorLeft = 0;
// Rightmost column - no right margin
if (column == maxColumn)
factorRight = 0;
fe.Margin = new Thickness(ChildMargin.Left*factorLeft,
ChildMargin.Top*factorTop,
ChildMargin.Right*factorRight,
ChildMargin.Bottom*factorBottom);
}
}
}
// We change all children's margins in MeasureOverride, since this is called right before
// the layouting takes place. I was first skeptical to do this here, because I thought changing
// the margin will trigger a LayoutUpdate, which in turn would lead to an endless recursion,
// but apparantly WPF takes care of this.
protected override Size MeasureOverride(Size availableSize)
{
UpdateChildMargins();
return base.MeasureOverride(availableSize);
}
}
}

View File

@ -0,0 +1,112 @@
using System.Windows;
using System.Windows.Controls;
namespace PettingZoo.Infrastructure
{
// Source: http://blog.functionalfun.net/2008/06/wpf-passwordbox-and-data-binding.html
public static class PasswordBoxAssistant
{
public static readonly DependencyProperty BoundPassword =
DependencyProperty.RegisterAttached("BoundPassword", typeof (string), typeof (PasswordBoxAssistant),
new PropertyMetadata(string.Empty, OnBoundPasswordChanged));
public static readonly DependencyProperty BindPassword = DependencyProperty.RegisterAttached(
"BindPassword", typeof (bool), typeof (PasswordBoxAssistant),
new PropertyMetadata(false, OnBindPasswordChanged));
private static readonly DependencyProperty UpdatingPassword =
DependencyProperty.RegisterAttached("UpdatingPassword", typeof (bool), typeof (PasswordBoxAssistant),
new PropertyMetadata(false));
private static void OnBoundPasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
PasswordBox box = d as PasswordBox;
// only handle this event when the property is attached to a PasswordBox
// and when the BindPassword attached property has been set to true
if (d == null || !GetBindPassword(d))
{
return;
}
// avoid recursive updating by ignoring the box's changed event
box.PasswordChanged -= HandlePasswordChanged;
string newPassword = (string) e.NewValue;
if (!GetUpdatingPassword(box))
{
box.Password = newPassword;
}
box.PasswordChanged += HandlePasswordChanged;
}
private static void OnBindPasswordChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
{
// when the BindPassword attached property is set on a PasswordBox,
// start listening to its PasswordChanged event
PasswordBox box = dp as PasswordBox;
if (box == null)
{
return;
}
bool wasBound = (bool) (e.OldValue);
bool needToBind = (bool) (e.NewValue);
if (wasBound)
{
box.PasswordChanged -= HandlePasswordChanged;
}
if (needToBind)
{
box.PasswordChanged += HandlePasswordChanged;
}
}
private static void HandlePasswordChanged(object sender, RoutedEventArgs e)
{
PasswordBox box = sender as PasswordBox;
// set a flag to indicate that we're updating the password
SetUpdatingPassword(box, true);
// push the new password into the BoundPassword property
SetBoundPassword(box, box.Password);
SetUpdatingPassword(box, false);
}
public static void SetBindPassword(DependencyObject dp, bool value)
{
dp.SetValue(BindPassword, value);
}
public static bool GetBindPassword(DependencyObject dp)
{
return (bool) dp.GetValue(BindPassword);
}
public static string GetBoundPassword(DependencyObject dp)
{
return (string) dp.GetValue(BoundPassword);
}
public static void SetBoundPassword(DependencyObject dp, string value)
{
dp.SetValue(BoundPassword, value);
}
private static bool GetUpdatingPassword(DependencyObject dp)
{
return (bool) dp.GetValue(UpdatingPassword);
}
private static void SetUpdatingPassword(DependencyObject dp, bool value)
{
dp.SetValue(UpdatingPassword, value);
}
}
}

View File

@ -1,6 +1,8 @@
namespace PettingZoo.Model using System;
namespace PettingZoo.Model
{ {
public interface IConnection public interface IConnection : IDisposable
{ {
} }
} }

View File

@ -6,5 +6,10 @@
{ {
} }
public void Dispose()
{
}
} }
} }

View File

@ -50,7 +50,8 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<StartupObject>PettingZoo.Program</StartupObject> <StartupObject>
</StartupObject>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="SimpleInjector, Version=3.1.5.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL"> <Reference Include="SimpleInjector, Version=3.1.5.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
@ -76,6 +77,10 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</ApplicationDefinition> </ApplicationDefinition>
<Page Include="Style.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="View\ConnectionWindow.xaml"> <Page Include="View\ConnectionWindow.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
@ -90,15 +95,16 @@
</Compile> </Compile>
<Compile Include="Infrastructure\DelegateCommand.cs" /> <Compile Include="Infrastructure\DelegateCommand.cs" />
<Compile Include="Infrastructure\BaseViewModel.cs" /> <Compile Include="Infrastructure\BaseViewModel.cs" />
<Compile Include="Infrastructure\GridLayout.cs" />
<Compile Include="Infrastructure\PasswordBoxAssistant.cs" />
<Compile Include="Model\IConnection.cs" /> <Compile Include="Model\IConnection.cs" />
<Compile Include="Model\IConnectionFactory.cs" /> <Compile Include="Model\IConnectionFactory.cs" />
<Compile Include="Model\IConnectionInfoBuilder.cs" /> <Compile Include="Model\IConnectionInfoBuilder.cs" />
<Compile Include="Model\ConnectionInfo.cs" /> <Compile Include="Model\ConnectionInfo.cs" />
<Compile Include="Model\RabbitMQClientConnection.cs" /> <Compile Include="Model\RabbitMQClientConnection.cs" />
<Compile Include="Model\RabbitMQClientConnectionFactory.cs" /> <Compile Include="Model\RabbitMQClientConnectionFactory.cs" />
<Compile Include="Program.cs" /> <Compile Include="ViewModel\ConnectionViewModel.cs" />
<Compile Include="ViewModel\ConnectionWindowViewModel.cs" /> <Compile Include="ViewModel\MainViewModel.cs" />
<Compile Include="ViewModel\MainBaseViewModel.cs" />
<Compile Include="View\ConnectionWindow.xaml.cs"> <Compile Include="View\ConnectionWindow.xaml.cs">
<DependentUpon>ConnectionWindow.xaml</DependentUpon> <DependentUpon>ConnectionWindow.xaml</DependentUpon>
</Compile> </Compile>
@ -122,7 +128,7 @@
<DesignTimeSharedInput>True</DesignTimeSharedInput> <DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile> </Compile>
<EmbeddedResource Include="Properties\Resources.resx"> <EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator> <Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
<None Include="packages.config" /> <None Include="packages.config" />

View File

@ -1,46 +0,0 @@
using System;
using System.Linq;
using System.Reflection;
using PettingZoo.Model;
using PettingZoo.View;
using SimpleInjector;
namespace PettingZoo
{
static class Program
{
[STAThread]
static void Main()
{
var container = Bootstrap();
RunApplication(container);
}
private static Container Bootstrap()
{
var container = new Container();
container.Register<IConnectionFactory, RabbitMQClientConnectionFactory>();
container.Register<IConnectionInfoBuilder, WindowConnectionInfoBuilder>();
// Automatically register all Window and BaseViewModel descendants
foreach (var type in Assembly.GetExecutingAssembly().GetExportedTypes()
.Where(t => t.IsSubclassOf(typeof(System.Windows.Window)) ||
t.IsSubclassOf(typeof(Infrastructure.BaseViewModel))))
{
container.Register(type);
}
return container;
}
private static void RunApplication(Container container)
{
var app = new App();
var mainWindow = container.GetInstance<MainWindow>();
app.Run(mainWindow);
}
}
}

View File

@ -8,10 +8,10 @@
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace PettingZoo.Properties namespace PettingZoo.Properties {
{ using System;
/// <summary> /// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc. /// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary> /// </summary>
@ -22,50 +22,141 @@ namespace PettingZoo.Properties
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources public class Resources {
{
private static global::System.Resources.ResourceManager resourceMan; private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture; private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() internal Resources() {
{
} }
/// <summary> /// <summary>
/// Returns the cached ResourceManager instance used by this class. /// Returns the cached ResourceManager instance used by this class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager public static global::System.Resources.ResourceManager ResourceManager {
{ get {
get if (object.ReferenceEquals(resourceMan, null)) {
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PettingZoo.Properties.Resources", typeof(Resources).Assembly); global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PettingZoo.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp; resourceMan = temp;
} }
return resourceMan; return resourceMan;
} }
} }
/// <summary> /// <summary>
/// Overrides the current thread's CurrentUICulture property for all /// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class. /// resource lookups using this strongly typed resource class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture public static global::System.Globalization.CultureInfo Culture {
{ get {
get
{
return resourceCulture; return resourceCulture;
} }
set set {
{
resourceCulture = value; resourceCulture = value;
} }
} }
/// <summary>
/// Looks up a localized string similar to Cancel.
/// </summary>
public static string ButtonCancel {
get {
return ResourceManager.GetString("ButtonCancel", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to OK.
/// </summary>
public static string ButtonOK {
get {
return ResourceManager.GetString("ButtonOK", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Exchange:.
/// </summary>
public static string ConnectionExchange {
get {
return ResourceManager.GetString("ConnectionExchange", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Host:.
/// </summary>
public static string ConnectionHost {
get {
return ResourceManager.GetString("ConnectionHost", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Password:.
/// </summary>
public static string ConnectionPassword {
get {
return ResourceManager.GetString("ConnectionPassword", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Port:.
/// </summary>
public static string ConnectionPort {
get {
return ResourceManager.GetString("ConnectionPort", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Routing key:.
/// </summary>
public static string ConnectionRoutingKey {
get {
return ResourceManager.GetString("ConnectionRoutingKey", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Username:.
/// </summary>
public static string ConnectionUsername {
get {
return ResourceManager.GetString("ConnectionUsername", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Virtual host:.
/// </summary>
public static string ConnectionVirtualHost {
get {
return ResourceManager.GetString("ConnectionVirtualHost", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Connection parameters.
/// </summary>
public static string ConnectionWindowTitle {
get {
return ResourceManager.GetString("ConnectionWindowTitle", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Petting Zoo - a RabbitMQ Message Viewer.
/// </summary>
public static string MainWindowTitle {
get {
return ResourceManager.GetString("MainWindowTitle", resourceCulture);
}
}
} }
} }

View File

@ -46,7 +46,7 @@
mimetype: application/x-microsoft.net.object.binary.base64 mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64 mimetype: application/x-microsoft.net.object.soap.base64
@ -60,6 +60,7 @@
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
--> -->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true"> <xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType> <xsd:complexType>
<xsd:choice maxOccurs="unbounded"> <xsd:choice maxOccurs="unbounded">
@ -68,9 +69,10 @@
<xsd:sequence> <xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" /> <xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence> </xsd:sequence>
<xsd:attribute name="name" type="xsd:string" /> <xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" /> <xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" /> <xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
<xsd:element name="assembly"> <xsd:element name="assembly">
@ -85,9 +87,10 @@
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence> </xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
<xsd:element name="resheader"> <xsd:element name="resheader">
@ -109,9 +112,42 @@
<value>2.0</value> <value>2.0</value>
</resheader> </resheader>
<resheader name="reader"> <resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="ButtonCancel" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="ButtonOK" xml:space="preserve">
<value>OK</value>
</data>
<data name="ConnectionExchange" xml:space="preserve">
<value>Exchange:</value>
</data>
<data name="ConnectionHost" xml:space="preserve">
<value>Host:</value>
</data>
<data name="ConnectionPassword" xml:space="preserve">
<value>Password:</value>
</data>
<data name="ConnectionPort" xml:space="preserve">
<value>Port:</value>
</data>
<data name="ConnectionRoutingKey" xml:space="preserve">
<value>Routing key:</value>
</data>
<data name="ConnectionUsername" xml:space="preserve">
<value>Username:</value>
</data>
<data name="ConnectionVirtualHost" xml:space="preserve">
<value>Virtual host:</value>
</data>
<data name="ConnectionWindowTitle" xml:space="preserve">
<value>Connection parameters</value>
</data>
<data name="MainWindowTitle" xml:space="preserve">
<value>Petting Zoo - a RabbitMQ Message Viewer</value>
</data>
</root> </root>

26
Style.xaml Normal file
View File

@ -0,0 +1,26 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:infrastructure="clr-namespace:PettingZoo.Infrastructure">
<!-- Global styling -->
<Style x:Key="WindowStyle" TargetType="{x:Type Window}">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
</Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Padding" Value="8,4"/>
</Style>
<!-- Explicit styling -->
<Style x:Key="FooterPanel" TargetType="{x:Type Panel}">
<Setter Property="Margin" Value="0,8,0,0" />
</Style>
<Style x:Key="FooterButton" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Margin" Value="8,0,0,0" />
</Style>
<Style x:Key="Form" TargetType="{x:Type infrastructure:GridLayout}">
<Setter Property="ChildMargin" Value="4"/>
</Style>
</ResourceDictionary>

View File

@ -1,8 +1,61 @@
<Window x:Class="PettingZoo.View.ConnectionWindow" <Window x:Class="PettingZoo.View.ConnectionWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ConnectionWindow" Height="300" Width="300"> xmlns:res="clr-namespace:PettingZoo.Properties"
<Grid> xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:viewModel="clr-namespace:PettingZoo.ViewModel"
xmlns:infrastructure="clr-namespace:PettingZoo.Infrastructure"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance viewModel:ConnectionViewModel}"
Width="500"
SizeToContent="Height"
ResizeMode="NoResize"
WindowStyle="ToolWindow"
Style="{StaticResource WindowStyle}"
Title="{x:Static res:Resources.ConnectionWindowTitle}"
FocusManager.FocusedElement="{Binding ElementName=HostTextBox}">
<DockPanel Margin="8">
<UniformGrid DockPanel.Dock="Bottom" HorizontalAlignment="Right" Rows="1" Columns="2" Style="{StaticResource FooterPanel}">
<Button IsDefault="True" Content="{x:Static res:Resources.ButtonOK}" Style="{StaticResource FooterButton}"/>
<Button IsCancel="True" Content="{x:Static res:Resources.ButtonCancel}" Style="{StaticResource FooterButton}"/>
</UniformGrid>
</Grid> <infrastructure:GridLayout Style="{StaticResource Form}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="8"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Grid.Column="0" Grid.Row="0" Content="{x:Static res:Resources.ConnectionHost}"/>
<TextBox Grid.Column="1" Grid.Row="0" Text="{Binding ConnectionInfo.Host}" Name="HostTextBox" />
<Label Grid.Column="0" Grid.Row="1" Content="{x:Static res:Resources.ConnectionPort}"/>
<Label Grid.Column="0" Grid.Row="2" Content="{x:Static res:Resources.ConnectionVirtualHost}"/>
<TextBox Grid.Column="1" Grid.Row="2" Text="{Binding ConnectionInfo.VirtualHost}"/>
<Label Grid.Column="0" Grid.Row="3" Content="{x:Static res:Resources.ConnectionUsername}"/>
<TextBox Grid.Column="1" Grid.Row="3" Text="{Binding ConnectionInfo.Username}"/>
<Label Grid.Column="0" Grid.Row="4" Content="{x:Static res:Resources.ConnectionPassword}"/>
<PasswordBox Grid.Column="1" Grid.Row="4" infrastructure:PasswordBoxAssistant.BindPassword="true" infrastructure:PasswordBoxAssistant.BoundPassword="{Binding Path=ConnectionInfo.Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<Label Grid.Column="0" Grid.Row="6" Content="{x:Static res:Resources.ConnectionExchange}"/>
<TextBox Grid.Column="1" Grid.Row="6" Text="{Binding Exchange}"/>
<Label Grid.Column="0" Grid.Row="7" Content="{x:Static res:Resources.ConnectionRoutingKey}"/>
<TextBox Grid.Column="1" Grid.Row="7" Text="{Binding RoutingKey}"/>
</infrastructure:GridLayout>
</DockPanel>
</Window> </Window>

View File

@ -8,7 +8,7 @@ namespace PettingZoo.View
{ {
public ConnectionInfo Build() public ConnectionInfo Build()
{ {
var viewModel = new ConnectionWindowViewModel(); var viewModel = new ConnectionViewModel();
var dialog = new ConnectionWindow(viewModel) var dialog = new ConnectionWindow(viewModel)
{ {
Owner = Application.Current.MainWindow Owner = Application.Current.MainWindow
@ -24,8 +24,10 @@ namespace PettingZoo.View
public partial class ConnectionWindow : Window public partial class ConnectionWindow : Window
{ {
public ConnectionWindow(ConnectionWindowViewModel viewModel) public ConnectionWindow(ConnectionViewModel viewModel)
{ {
WindowStartupLocation = WindowStartupLocation.CenterOwner;
InitializeComponent(); InitializeComponent();
DataContext = viewModel; DataContext = viewModel;
} }

View File

@ -1,13 +1,29 @@
<Window x:Class="PettingZoo.View.MainWindow" <Window x:Class="PettingZoo.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Petting Zoo - a RabbitMQ Message Viewer" Height="600" Width="800"> xmlns:res="clr-namespace:PettingZoo.Properties"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:viewModel="clr-namespace:PettingZoo.ViewModel"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance viewModel:MainViewModel}"
Width="800"
Height="600"
ResizeMode="CanResizeWithGrip"
Style="{StaticResource WindowStyle}"
Title="{x:Static res:Resources.MainWindowTitle}">
<DockPanel> <DockPanel>
<ToolBarTray DockPanel.Dock="Top"> <ToolBar DockPanel.Dock="Top" ToolBarTray.IsLocked="True">
<ToolBar> <Button Command="{Binding ConnectCommand}" Content="Connect"></Button>
<Button Command=""></Button> <Button Command="{Binding DisconnectCommand}" Content="Disconnect"></Button>
</ToolBar> <Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" />
</ToolBarTray> <Button Command="{Binding ClearCommand}" Content="Clear messages"></Button>
</ToolBar>
<StatusBar DockPanel.Dock="Bottom">
<StatusBarItem>
<TextBlock />
</StatusBarItem>
</StatusBar>
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />

View File

@ -1,15 +1,18 @@
using System.Windows; using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using PettingZoo.ViewModel; using PettingZoo.ViewModel;
namespace PettingZoo.View namespace PettingZoo.View
{ {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window public partial class MainWindow : Window
{ {
public MainWindow(MainBaseViewModel viewModel) public MainWindow(MainViewModel viewModel)
{ {
WindowStartupLocation = WindowStartupLocation.CenterScreen;
InitializeComponent(); InitializeComponent();
DataContext = viewModel; DataContext = viewModel;
} }

View File

@ -2,8 +2,10 @@
namespace PettingZoo.ViewModel namespace PettingZoo.ViewModel
{ {
public class ConnectionWindowViewModel public class ConnectionViewModel
{ {
public ConnectionInfo ConnectionInfo { get; set; } public ConnectionInfo ConnectionInfo { get; set; }
public string Exchange { get; set; }
public string RoutingKey { get; set; }
} }
} }

View File

@ -1,53 +0,0 @@
using System.Windows.Input;
using PettingZoo.Infrastructure;
using PettingZoo.Model;
namespace PettingZoo.ViewModel
{
public class MainBaseViewModel : BaseViewModel
{
private readonly IConnectionInfoBuilder connectionInfoBuilder;
private readonly IConnectionFactory connectionFactory;
private ConnectionInfo connectionInfo;
private IConnection connection;
public ConnectionInfo ConnectionInfo {
get
{
return connectionInfo;
}
private set
{
if (value != connectionInfo)
{
connectionInfo = value;
RaisePropertyChanged();
}
}
}
public ICommand ConnectCommand { get; private set; }
public MainBaseViewModel(IConnectionInfoBuilder connectionInfoBuilder, IConnectionFactory connectionFactory)
{
this.connectionInfoBuilder = connectionInfoBuilder;
this.connectionFactory = connectionFactory;
ConnectCommand = new DelegateCommand(ConnectExecute);
}
protected void ConnectExecute()
{
var newInfo = connectionInfoBuilder.Build();
if (newInfo != null)
{
ConnectionInfo = newInfo;
connection = connectionFactory.CreateConnection(connectionInfo);
}
}
}
}

View File

@ -0,0 +1,92 @@
using System.Windows.Input;
using PettingZoo.Infrastructure;
using PettingZoo.Model;
namespace PettingZoo.ViewModel
{
public class MainViewModel : BaseViewModel
{
private readonly IConnectionInfoBuilder connectionInfoBuilder;
private readonly IConnectionFactory connectionFactory;
private ConnectionInfo connectionInfo;
private IConnection connection;
private readonly DelegateCommand connectCommand;
private readonly DelegateCommand disconnectCommand;
private readonly DelegateCommand clearCommand;
public ConnectionInfo ConnectionInfo {
get
{
return connectionInfo;
}
private set
{
if (value != connectionInfo)
{
connectionInfo = value;
RaisePropertyChanged();
}
}
}
public ICommand ConnectCommand { get { return connectCommand; } }
public ICommand DisconnectCommand { get { return disconnectCommand; } }
public ICommand ClearCommand { get { return clearCommand; } }
public MainViewModel(IConnectionInfoBuilder connectionInfoBuilder, IConnectionFactory connectionFactory)
{
this.connectionInfoBuilder = connectionInfoBuilder;
this.connectionFactory = connectionFactory;
connectCommand = new DelegateCommand(ConnectExecute);
disconnectCommand = new DelegateCommand(DisconnectExecute, DisconnectCanExecute);
clearCommand = new DelegateCommand(ClearExecute, ClearCanExecute);
}
private void ConnectExecute()
{
var newInfo = connectionInfoBuilder.Build();
if (newInfo == null)
return;
ConnectionInfo = newInfo;
connection = connectionFactory.CreateConnection(connectionInfo);
disconnectCommand.RaiseCanExecuteChanged();
}
private void DisconnectExecute()
{
if (connection != null)
{
connection.Dispose();
connection = null;
}
ConnectionInfo = null;
}
private bool DisconnectCanExecute()
{
return connection != null;
}
private void ClearExecute()
{
}
private bool ClearCanExecute()
{
return false;
}
}
}