Live RabbitMQ connection, Json pretty-printing and further tweaks
This commit is contained in:
parent
ceb2e386f4
commit
05a6e380e4
12
App.xaml.cs
12
App.xaml.cs
@ -1,6 +1,8 @@
|
|||||||
using System.Linq;
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Markup;
|
||||||
using PettingZoo.Model;
|
using PettingZoo.Model;
|
||||||
using PettingZoo.View;
|
using PettingZoo.View;
|
||||||
using SimpleInjector;
|
using SimpleInjector;
|
||||||
@ -11,8 +13,12 @@ namespace PettingZoo
|
|||||||
{
|
{
|
||||||
public void ApplicationStartup(object sender, StartupEventArgs e)
|
public void ApplicationStartup(object sender, StartupEventArgs e)
|
||||||
{
|
{
|
||||||
|
// WPF defaults to US for date formatting in bindings, this fixes it
|
||||||
|
FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement), new FrameworkPropertyMetadata(
|
||||||
|
XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));
|
||||||
|
|
||||||
var container = Bootstrap();
|
var container = Bootstrap();
|
||||||
RunApplication(container);
|
RunApplication(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -38,6 +44,8 @@ namespace PettingZoo
|
|||||||
private static void RunApplication(Container container)
|
private static void RunApplication(Container container)
|
||||||
{
|
{
|
||||||
var mainWindow = container.GetInstance<MainWindow>();
|
var mainWindow = container.GetInstance<MainWindow>();
|
||||||
|
mainWindow.Closed += (sender, args) => container.Dispose();
|
||||||
|
|
||||||
mainWindow.Show();
|
mainWindow.Show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
Images/Connect.png
Normal file
BIN
Images/Connect.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
BIN
Images/Disconnect.png
Normal file
BIN
Images/Disconnect.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
4900
Images/PettingZoo.ai
Normal file
4900
Images/PettingZoo.ai
Normal file
File diff suppressed because one or more lines are too long
BIN
Images/PettingZoo.ico
Normal file
BIN
Images/PettingZoo.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
@ -51,7 +51,7 @@ namespace PettingZoo.Infrastructure
|
|||||||
ItemsSourcePropertyChanged));
|
ItemsSourcePropertyChanged));
|
||||||
|
|
||||||
private readonly System.Windows.Controls.ListBox target;
|
private readonly System.Windows.Controls.ListBox target;
|
||||||
private ScrollViewer scrollViewer = null;
|
private ScrollViewer scrollViewer;
|
||||||
|
|
||||||
public AutoScrollHandler(System.Windows.Controls.ListBox target)
|
public AutoScrollHandler(System.Windows.Controls.ListBox target)
|
||||||
{
|
{
|
||||||
|
@ -1,27 +1,42 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace PettingZoo.Model
|
namespace PettingZoo.Model
|
||||||
{
|
{
|
||||||
public class MessageBodyRenderer
|
public class MessageBodyRenderer
|
||||||
{
|
{
|
||||||
public static List<String> TextTypes = new List<string>
|
public static Dictionary<string, Func<byte[], string>> ContentTypeHandlers = new Dictionary<string, Func<byte[], string>>
|
||||||
{
|
{
|
||||||
"application/json",
|
{ "application/json", RenderJson }
|
||||||
"application/xml"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
public static string Render(byte[] body, string contentType = "")
|
public static string Render(byte[] body, string contentType = "")
|
||||||
{
|
{
|
||||||
if (TextTypes.Contains(contentType))
|
Func<byte[], string> handler;
|
||||||
{
|
|
||||||
return Encoding.UTF8.GetString(body);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToDo hex output
|
if (ContentTypeHandlers.TryGetValue(contentType, out handler))
|
||||||
return "";
|
return handler(body);
|
||||||
|
|
||||||
|
// ToDo hex output if required
|
||||||
|
return Encoding.UTF8.GetString(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static string RenderJson(byte[] body)
|
||||||
|
{
|
||||||
|
var bodyText = Encoding.UTF8.GetString(body);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var obj = JsonConvert.DeserializeObject(bodyText);
|
||||||
|
return JsonConvert.SerializeObject(obj, Formatting.Indented);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return bodyText;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ namespace PettingZoo.Model
|
|||||||
public class MessageInfo
|
public class MessageInfo
|
||||||
{
|
{
|
||||||
public DateTime Timestamp { get; set; }
|
public DateTime Timestamp { get; set; }
|
||||||
|
public string Exchange { get; set; }
|
||||||
public string RoutingKey { get; set; }
|
public string RoutingKey { get; set; }
|
||||||
public byte[] Body { get; set; }
|
public byte[] Body { get; set; }
|
||||||
|
|
||||||
@ -15,8 +16,8 @@ namespace PettingZoo.Model
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return Properties != null && Properties.ContainsKey("content-type")
|
return Properties != null && Properties.ContainsKey(RabbitMQProperties.ContentType)
|
||||||
? Properties["content-type"]
|
? Properties[RabbitMQProperties.ContentType]
|
||||||
: "";
|
: "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,50 +1,161 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using PettingZoo.Properties;
|
||||||
|
using RabbitMQ.Client;
|
||||||
|
using RabbitMQ.Client.Events;
|
||||||
|
|
||||||
namespace PettingZoo.Model
|
namespace PettingZoo.Model
|
||||||
{
|
{
|
||||||
public class RabbitMQClientConnection : IConnection
|
public class RabbitMQClientConnection : IConnection
|
||||||
{
|
{
|
||||||
private readonly CancellationTokenSource timer;
|
private readonly CancellationTokenSource connectionTaskToken;
|
||||||
|
private RabbitMQ.Client.IConnection connection;
|
||||||
|
private IModel model;
|
||||||
|
|
||||||
|
|
||||||
|
public event EventHandler<MessageReceivedEventArgs> MessageReceived;
|
||||||
|
|
||||||
|
|
||||||
public RabbitMQClientConnection(ConnectionInfo connectionInfo)
|
public RabbitMQClientConnection(ConnectionInfo connectionInfo)
|
||||||
{
|
{
|
||||||
timer = new CancellationTokenSource();
|
connectionTaskToken = new CancellationTokenSource();
|
||||||
var token = timer.Token;
|
var connectionToken = connectionTaskToken.Token;
|
||||||
|
|
||||||
Task.Run(() =>
|
Task.Factory.StartNew(() => TryConnection(connectionInfo, connectionToken), connectionToken);
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (token.IsCancellationRequested)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (MessageReceived != null)
|
|
||||||
MessageReceived(null, new MessageReceivedEventArgs(new MessageInfo
|
|
||||||
{
|
|
||||||
RoutingKey = "test",
|
|
||||||
Body = Encoding.UTF8.GetBytes("{ \"hello\": \"world\" }"),
|
|
||||||
Properties = new Dictionary<string, string>
|
|
||||||
{
|
|
||||||
{ "content-type", "application/json" },
|
|
||||||
{ "classType", "LEF.Messaging.Internal.ActieNewMessage" }
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
Thread.Sleep(200);
|
|
||||||
}
|
|
||||||
}, token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
timer.Cancel();
|
connectionTaskToken.Cancel();
|
||||||
|
|
||||||
|
if (model != null)
|
||||||
|
{
|
||||||
|
model.Dispose();
|
||||||
|
model = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connection != null)
|
||||||
|
{
|
||||||
|
connection.Dispose();
|
||||||
|
connection = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public event EventHandler<MessageReceivedEventArgs> MessageReceived;
|
private void TryConnection(ConnectionInfo connectionInfo, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var factory = new ConnectionFactory
|
||||||
|
{
|
||||||
|
HostName = connectionInfo.Host,
|
||||||
|
Port = connectionInfo.Port,
|
||||||
|
VirtualHost = connectionInfo.VirtualHost,
|
||||||
|
UserName = connectionInfo.Username,
|
||||||
|
Password = connectionInfo.Password
|
||||||
|
};
|
||||||
|
|
||||||
|
// ToDo exception handling
|
||||||
|
connection = factory.CreateConnection();
|
||||||
|
model = connection.CreateModel();
|
||||||
|
|
||||||
|
var queueName = model.QueueDeclare().QueueName;
|
||||||
|
model.QueueBind(queueName, connectionInfo.Exchange, connectionInfo.RoutingKey);
|
||||||
|
|
||||||
|
|
||||||
|
var consumer = new EventingBasicConsumer(model);
|
||||||
|
consumer.Received += ClientReceived;
|
||||||
|
|
||||||
|
model.BasicConsume(queueName, true, consumer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void ClientReceived(object sender, BasicDeliverEventArgs args)
|
||||||
|
{
|
||||||
|
if (MessageReceived == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MessageReceived(this, new MessageReceivedEventArgs(
|
||||||
|
new MessageInfo
|
||||||
|
{
|
||||||
|
Exchange = args.Exchange,
|
||||||
|
RoutingKey = args.RoutingKey,
|
||||||
|
Body = args.Body,
|
||||||
|
Properties = ConvertProperties(args.BasicProperties)
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static Dictionary<string, string> ConvertProperties(IBasicProperties basicProperties)
|
||||||
|
{
|
||||||
|
var properties = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
if (basicProperties.IsDeliveryModePresent())
|
||||||
|
{
|
||||||
|
string deliveryMode;
|
||||||
|
|
||||||
|
switch (basicProperties.DeliveryMode)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
deliveryMode = Resources.DeliveryModeNonPersistent;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
deliveryMode = Resources.DeliveryModePersistent;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
deliveryMode = basicProperties.DeliveryMode.ToString(CultureInfo.InvariantCulture);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
properties.Add(RabbitMQProperties.DeliveryMode, deliveryMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (basicProperties.IsContentTypePresent())
|
||||||
|
properties.Add(RabbitMQProperties.ContentType, basicProperties.ContentType);
|
||||||
|
|
||||||
|
if (basicProperties.IsContentEncodingPresent())
|
||||||
|
properties.Add(RabbitMQProperties.ContentEncoding, basicProperties.ContentEncoding);
|
||||||
|
|
||||||
|
if (basicProperties.IsPriorityPresent())
|
||||||
|
properties.Add(RabbitMQProperties.Priority, basicProperties.Priority.ToString(CultureInfo.InvariantCulture));
|
||||||
|
|
||||||
|
if (basicProperties.IsCorrelationIdPresent())
|
||||||
|
properties.Add(RabbitMQProperties.Priority, basicProperties.CorrelationId);
|
||||||
|
|
||||||
|
if (basicProperties.IsReplyToPresent())
|
||||||
|
properties.Add(RabbitMQProperties.ReplyTo, basicProperties.ReplyTo);
|
||||||
|
|
||||||
|
if (basicProperties.IsExpirationPresent())
|
||||||
|
properties.Add(RabbitMQProperties.Expiration, basicProperties.Expiration);
|
||||||
|
|
||||||
|
if (basicProperties.IsMessageIdPresent())
|
||||||
|
properties.Add(RabbitMQProperties.MessageId, basicProperties.MessageId);
|
||||||
|
|
||||||
|
if (basicProperties.IsTimestampPresent())
|
||||||
|
properties.Add(RabbitMQProperties.Timestamp, basicProperties.Timestamp.UnixTime.ToString(CultureInfo.InvariantCulture));
|
||||||
|
|
||||||
|
if (basicProperties.IsTypePresent())
|
||||||
|
properties.Add(RabbitMQProperties.Type, basicProperties.Type);
|
||||||
|
|
||||||
|
if (basicProperties.IsUserIdPresent())
|
||||||
|
properties.Add(RabbitMQProperties.UserId, basicProperties.UserId);
|
||||||
|
|
||||||
|
if (basicProperties.IsAppIdPresent())
|
||||||
|
properties.Add(RabbitMQProperties.UserId, basicProperties.AppId);
|
||||||
|
|
||||||
|
if (basicProperties.IsClusterIdPresent())
|
||||||
|
properties.Add(RabbitMQProperties.ClusterId, basicProperties.ClusterId);
|
||||||
|
|
||||||
|
foreach (var header in basicProperties.Headers)
|
||||||
|
properties.Add(header.Key, Encoding.UTF8.GetString((byte[])header.Value));
|
||||||
|
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
19
Model/RabbitMQProperties.cs
Normal file
19
Model/RabbitMQProperties.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
namespace PettingZoo.Model
|
||||||
|
{
|
||||||
|
static class RabbitMQProperties
|
||||||
|
{
|
||||||
|
public const string ContentType = "content-type";
|
||||||
|
public const string ContentEncoding = "content-encoding";
|
||||||
|
public const string DeliveryMode = "delivery-mode";
|
||||||
|
public const string Priority = "priority";
|
||||||
|
public const string CorrelationId = "correlation-id";
|
||||||
|
public const string ReplyTo = "reply-to";
|
||||||
|
public const string Expiration = "expiration";
|
||||||
|
public const string MessageId = "message-id";
|
||||||
|
public const string Timestamp = "timestamp";
|
||||||
|
public const string Type = "type";
|
||||||
|
public const string UserId = "user-id";
|
||||||
|
public const string AppId = "app-id";
|
||||||
|
public const string ClusterId = "cluster-id";
|
||||||
|
}
|
||||||
|
}
|
@ -53,11 +53,22 @@
|
|||||||
<StartupObject>
|
<StartupObject>
|
||||||
</StartupObject>
|
</StartupObject>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ApplicationIcon>PettingZoo.ico</ApplicationIcon>
|
||||||
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="AutoMapper, Version=4.2.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
|
<Reference Include="AutoMapper, Version=4.2.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
|
||||||
<HintPath>packages\AutoMapper.4.2.1\lib\net45\AutoMapper.dll</HintPath>
|
<HintPath>packages\AutoMapper.4.2.1\lib\net45\AutoMapper.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
|
<HintPath>packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="RabbitMQ.Client, Version=3.6.2.0, Culture=neutral, PublicKeyToken=89e7d7c5feba84ce, processorArchitecture=MSIL">
|
||||||
|
<HintPath>packages\RabbitMQ.Client.3.6.2\lib\net45\RabbitMQ.Client.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
<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">
|
||||||
<HintPath>packages\SimpleInjector.3.1.5\lib\net45\SimpleInjector.dll</HintPath>
|
<HintPath>packages\SimpleInjector.3.1.5\lib\net45\SimpleInjector.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
@ -110,6 +121,7 @@
|
|||||||
<Compile Include="Model\MessageInfo.cs" />
|
<Compile Include="Model\MessageInfo.cs" />
|
||||||
<Compile Include="Model\RabbitMQClientConnection.cs" />
|
<Compile Include="Model\RabbitMQClientConnection.cs" />
|
||||||
<Compile Include="Model\RabbitMQClientConnectionFactory.cs" />
|
<Compile Include="Model\RabbitMQClientConnectionFactory.cs" />
|
||||||
|
<Compile Include="Model\RabbitMQProperties.cs" />
|
||||||
<Compile Include="ViewModel\ConnectionViewModel.cs" />
|
<Compile Include="ViewModel\ConnectionViewModel.cs" />
|
||||||
<Compile Include="ViewModel\MainViewModel.cs" />
|
<Compile Include="ViewModel\MainViewModel.cs" />
|
||||||
<Compile Include="View\ConnectionWindow.xaml.cs">
|
<Compile Include="View\ConnectionWindow.xaml.cs">
|
||||||
@ -165,6 +177,13 @@
|
|||||||
<Install>false</Install>
|
<Install>false</Install>
|
||||||
</BootstrapperPackage>
|
</BootstrapperPackage>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Resource Include="Images\Connect.png" />
|
||||||
|
<Resource Include="Images\Disconnect.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Resource Include="PettingZoo.ico" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
BIN
PettingZoo.ico
Normal file
BIN
PettingZoo.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
21
Properties/Resources.Designer.cs
generated
21
Properties/Resources.Designer.cs
generated
@ -9,9 +9,6 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
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>
|
||||||
@ -150,6 +147,24 @@ namespace PettingZoo.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Non-persistent.
|
||||||
|
/// </summary>
|
||||||
|
public static string DeliveryModeNonPersistent {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("DeliveryModeNonPersistent", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Persistent.
|
||||||
|
/// </summary>
|
||||||
|
public static string DeliveryModePersistent {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("DeliveryModePersistent", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Petting Zoo - a RabbitMQ Message Viewer.
|
/// Looks up a localized string similar to Petting Zoo - a RabbitMQ Message Viewer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -147,6 +147,12 @@
|
|||||||
<data name="ConnectionWindowTitle" xml:space="preserve">
|
<data name="ConnectionWindowTitle" xml:space="preserve">
|
||||||
<value>Connection parameters</value>
|
<value>Connection parameters</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="DeliveryModeNonPersistent" xml:space="preserve">
|
||||||
|
<value>Non-persistent</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeliveryModePersistent" xml:space="preserve">
|
||||||
|
<value>Persistent</value>
|
||||||
|
</data>
|
||||||
<data name="MainWindowTitle" xml:space="preserve">
|
<data name="MainWindowTitle" xml:space="preserve">
|
||||||
<value>Petting Zoo - a RabbitMQ Message Viewer</value>
|
<value>Petting Zoo - a RabbitMQ Message Viewer</value>
|
||||||
</data>
|
</data>
|
||||||
|
21
Style.xaml
21
Style.xaml
@ -40,4 +40,25 @@
|
|||||||
<Setter Property="HorizontalGridLinesBrush" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
|
<Setter Property="HorizontalGridLinesBrush" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
|
||||||
<Setter Property="VerticalGridLinesBrush" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
|
<Setter Property="VerticalGridLinesBrush" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
|
||||||
|
<Style x:Key="ToolbarIcon" TargetType="{x:Type Image}">
|
||||||
|
<Style.Triggers>
|
||||||
|
<Trigger Property="IsEnabled" Value="False">
|
||||||
|
<Setter Property="Opacity" Value="0.25"/>
|
||||||
|
</Trigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
|
||||||
|
<Style x:Key="Timestamp" TargetType="{x:Type TextBlock}">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" Value="False">
|
||||||
|
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style x:Key="Routingkey" TargetType="{x:Type TextBlock}">
|
||||||
|
</Style>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
@ -15,10 +15,25 @@
|
|||||||
Title="{x:Static res:Resources.MainWindowTitle}">
|
Title="{x:Static res:Resources.MainWindowTitle}">
|
||||||
<DockPanel>
|
<DockPanel>
|
||||||
<ToolBar DockPanel.Dock="Top" ToolBarTray.IsLocked="True">
|
<ToolBar DockPanel.Dock="Top" ToolBarTray.IsLocked="True">
|
||||||
<Button Command="{Binding ConnectCommand}" Content="Connect"></Button>
|
<Button Command="{Binding ConnectCommand}">
|
||||||
<Button Command="{Binding DisconnectCommand}" Content="Disconnect"></Button>
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<Image Source="/Images/Connect.png" Width="16" Height="16" Style="{StaticResource ToolbarIcon}"/>
|
||||||
|
<TextBlock Margin="3,0,0,0">Connect</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
<Button Command="{Binding DisconnectCommand}">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<Image Source="/Images/Disconnect.png" Width="16" Height="16" Style="{StaticResource ToolbarIcon}"/>
|
||||||
|
<TextBlock Margin="3,0,0,0">Disconnect</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
<Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" />
|
<Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" />
|
||||||
<Button Command="{Binding ClearCommand}" Content="Clear messages"></Button>
|
<Button Command="{Binding ClearCommand}">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<Image Source="/Images/Disconnect.png" Width="16" Height="16" Style="{StaticResource ToolbarIcon}"/>
|
||||||
|
<TextBlock Margin="3,0,0,0">Clear messages</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
</ToolBar>
|
</ToolBar>
|
||||||
<StatusBar DockPanel.Dock="Bottom">
|
<StatusBar DockPanel.Dock="Bottom">
|
||||||
<StatusBarItem>
|
<StatusBarItem>
|
||||||
@ -43,8 +58,8 @@
|
|||||||
<ColumnDefinition Width="Auto" MinWidth="150"/>
|
<ColumnDefinition Width="Auto" MinWidth="150"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock Grid.Column="0" Grid.Row="0" Text="{Binding Timestamp}"></TextBlock>
|
<TextBlock Grid.Column="0" Grid.Row="0" Text="{Binding Timestamp, StringFormat=g}" Style="{StaticResource Timestamp}"></TextBlock>
|
||||||
<TextBlock Grid.Column="1" Grid.Row="0" Text="{Binding RoutingKey}"></TextBlock>
|
<TextBlock Grid.Column="1" Grid.Row="0" Text="{Binding RoutingKey}" Style="{StaticResource Routingkey}"></TextBlock>
|
||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListBox.ItemTemplate>
|
</ListBox.ItemTemplate>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Windows;
|
using System;
|
||||||
|
using System.Windows;
|
||||||
using PettingZoo.ViewModel;
|
using PettingZoo.ViewModel;
|
||||||
|
|
||||||
namespace PettingZoo.View
|
namespace PettingZoo.View
|
||||||
@ -11,6 +12,16 @@ namespace PettingZoo.View
|
|||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
DataContext = viewModel;
|
DataContext = viewModel;
|
||||||
|
|
||||||
|
Dispatcher.ShutdownStarted += OnDispatcherShutDownStarted;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void OnDispatcherShutDownStarted(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var disposable = DataContext as IDisposable;
|
||||||
|
if (!ReferenceEquals(null, disposable))
|
||||||
|
disposable.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ using PettingZoo.Model;
|
|||||||
|
|
||||||
namespace PettingZoo.ViewModel
|
namespace PettingZoo.ViewModel
|
||||||
{
|
{
|
||||||
public class MainViewModel : BaseViewModel
|
public class MainViewModel : BaseViewModel, IDisposable
|
||||||
{
|
{
|
||||||
private readonly TaskScheduler uiScheduler;
|
private readonly TaskScheduler uiScheduler;
|
||||||
private readonly IConnectionInfoBuilder connectionInfoBuilder;
|
private readonly IConnectionInfoBuilder connectionInfoBuilder;
|
||||||
@ -89,6 +89,16 @@ namespace PettingZoo.ViewModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (connection != null)
|
||||||
|
{
|
||||||
|
connection.Dispose();
|
||||||
|
connection = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void ConnectExecute()
|
private void ConnectExecute()
|
||||||
{
|
{
|
||||||
var newInfo = connectionInfoBuilder.Build();
|
var newInfo = connectionInfoBuilder.Build();
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="AutoMapper" version="4.2.1" targetFramework="net45" />
|
<package id="AutoMapper" version="4.2.1" targetFramework="net45" />
|
||||||
|
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net45" />
|
||||||
|
<package id="RabbitMQ.Client" version="3.6.2" targetFramework="net45" />
|
||||||
<package id="SimpleInjector" version="3.1.5" targetFramework="net45" />
|
<package id="SimpleInjector" version="3.1.5" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
Loading…
Reference in New Issue
Block a user