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>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Style.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</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
{
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>
</PropertyGroup>
<PropertyGroup>
<StartupObject>PettingZoo.Program</StartupObject>
<StartupObject>
</StartupObject>
</PropertyGroup>
<ItemGroup>
<Reference Include="SimpleInjector, Version=3.1.5.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
@ -76,6 +77,10 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="Style.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="View\ConnectionWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@ -90,15 +95,16 @@
</Compile>
<Compile Include="Infrastructure\DelegateCommand.cs" />
<Compile Include="Infrastructure\BaseViewModel.cs" />
<Compile Include="Infrastructure\GridLayout.cs" />
<Compile Include="Infrastructure\PasswordBoxAssistant.cs" />
<Compile Include="Model\IConnection.cs" />
<Compile Include="Model\IConnectionFactory.cs" />
<Compile Include="Model\IConnectionInfoBuilder.cs" />
<Compile Include="Model\ConnectionInfo.cs" />
<Compile Include="Model\RabbitMQClientConnection.cs" />
<Compile Include="Model\RabbitMQClientConnectionFactory.cs" />
<Compile Include="Program.cs" />
<Compile Include="ViewModel\ConnectionWindowViewModel.cs" />
<Compile Include="ViewModel\MainBaseViewModel.cs" />
<Compile Include="ViewModel\ConnectionViewModel.cs" />
<Compile Include="ViewModel\MainViewModel.cs" />
<Compile Include="View\ConnectionWindow.xaml.cs">
<DependentUpon>ConnectionWindow.xaml</DependentUpon>
</Compile>
@ -122,7 +128,7 @@
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<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,8 +8,8 @@
// </auto-generated>
//------------------------------------------------------------------------------
namespace PettingZoo.Properties
{
namespace PettingZoo.Properties {
using System;
/// <summary>
@ -22,28 +22,23 @@ namespace PettingZoo.Properties
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
public class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PettingZoo.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
@ -56,16 +51,112 @@ namespace PettingZoo.Properties
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set
{
set {
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
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
@ -60,6 +60,7 @@
: 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:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
@ -68,9 +69,10 @@
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</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="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
@ -85,9 +87,10 @@
<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: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="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
@ -109,9 +112,42 @@
<value>2.0</value>
</resheader>
<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 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>
<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>

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"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ConnectionWindow" Height="300" Width="300">
<Grid>
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"
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>

View File

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

View File

@ -1,13 +1,29 @@
<Window x:Class="PettingZoo.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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>
<ToolBarTray DockPanel.Dock="Top">
<ToolBar>
<Button Command=""></Button>
<ToolBar DockPanel.Dock="Top" ToolBarTray.IsLocked="True">
<Button Command="{Binding ConnectCommand}" Content="Connect"></Button>
<Button Command="{Binding DisconnectCommand}" Content="Disconnect"></Button>
<Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" />
<Button Command="{Binding ClearCommand}" Content="Clear messages"></Button>
</ToolBar>
</ToolBarTray>
<StatusBar DockPanel.Dock="Bottom">
<StatusBarItem>
<TextBlock />
</StatusBarItem>
</StatusBar>
<Grid>
<Grid.ColumnDefinitions>
<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;
namespace PettingZoo.View
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow(MainBaseViewModel viewModel)
public MainWindow(MainViewModel viewModel)
{
WindowStartupLocation = WindowStartupLocation.CenterScreen;
InitializeComponent();
DataContext = viewModel;
}

View File

@ -2,8 +2,10 @@
namespace PettingZoo.ViewModel
{
public class ConnectionWindowViewModel
public class ConnectionViewModel
{
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;
}
}
}