How can I use NLog's RichTextBox Target in WPF application? - wpf

How can I use RichTextBox Target in WPF application?
I don't want to have a separate window with log, I want all log messages to be outputted in richTextBox located in WPF dialog.
I've tried to use WindowsFormsHost with RichTextBox box inside but that does not worked for me: NLog opened separate Windows Form anyway.

A workaround in the mean time is to use the 3 classes available here, then follow this procedure:
Import the 3 files into your project
If not already the case, use Project > Add Reference to add references to the WPF assemblies: WindowsBase, PresentationCore, PresentationFramework.
In WpfRichTextBoxTarget.cs, replace lines 188-203 with:
//this.TargetRichTextBox.Invoke(new DelSendTheMessageToRichTextBox(this.SendTheMessageToRichTextBox), new object[] { logMessage, matchingRule });
if (System.Windows.Application.Current.Dispatcher.CheckAccess() == false) {
System.Windows.Application.Current.Dispatcher.Invoke(new Action(() => {
SendTheMessageToRichTextBox(logMessage, matchingRule);
}));
}
else {
SendTheMessageToRichTextBox(logMessage, matchingRule);
}
}
private static Color GetColorFromString(string color, Brush defaultColor) {
if (defaultColor == null) return Color.FromRgb(255, 255, 255); // This will set default background colour to white.
if (color == "Empty") {
return (Color)colorConverter.ConvertFrom(defaultColor);
}
return (Color)colorConverter.ConvertFromString(color);
}
In your code, configure the new target like this below example:
I hope it helps, but it definitely does not seem to be a comprehensive implementation...
public void loading() {
var target = new WpfRichTextBoxTarget();
target.Name = "console";
target.Layout = "${longdate:useUTC=true}|${level:uppercase=true}|${logger}::${message}";
target.ControlName = "rtbConsole"; // Name of the richtextbox control already on your window
target.FormName = "MonitorWindow"; // Name of your window where there is the richtextbox, but it seems it will not really be taken into account, the application mainwindow will be used instead.
target.AutoScroll = true;
target.MaxLines = 100000;
target.UseDefaultRowColoringRules = true;
AsyncTargetWrapper asyncWrapper = new AsyncTargetWrapper();
asyncWrapper.Name = "console";
asyncWrapper.WrappedTarget = target;
SimpleConfigurator.ConfigureForTargetLogging(asyncWrapper, LogLevel.Trace);
}

If you define a RichTextBoxTarget in the config file, a new form is automatically created. This is because NLog initializes before your (named) form and control has been created. Even if you haven't got any rules pointing to the target. Perhaps there is a better solution, but I solved it by creating the target programatically:
using NLog;
//[...]
RichTextBoxTarget target = new RichTextBoxTarget();
target.Name = "RichTextBox";
target.Layout = "${longdate} ${level:uppercase=true} ${logger} ${message}";
target.ControlName = "textbox1";
target.FormName = "Form1";
target.AutoScroll = true;
target.MaxLines = 10000;
target.UseDefaultRowColoringRules = false;
target.RowColoringRules.Add(
new RichTextBoxRowColoringRule(
"level == LogLevel.Trace", // condition
"DarkGray", // font color
"Control", // background color
FontStyle.Regular
)
);
target.RowColoringRules.Add(new RichTextBoxRowColoringRule("level == LogLevel.Debug", "Gray", "Control"));
target.RowColoringRules.Add(new RichTextBoxRowColoringRule("level == LogLevel.Info", "ControlText", "Control"));
target.RowColoringRules.Add(new RichTextBoxRowColoringRule("level == LogLevel.Warn", "DarkRed", "Control"));
target.RowColoringRules.Add(new RichTextBoxRowColoringRule("level == LogLevel.Error", "White", "DarkRed", FontStyle.Bold));
target.RowColoringRules.Add(new RichTextBoxRowColoringRule("level == LogLevel.Fatal", "Yellow", "DarkRed", FontStyle.Bold));
AsyncTargetWrapper asyncWrapper = new AsyncTargetWrapper();
asyncWrapper.Name = "AsyncRichTextBox";
asyncWrapper.WrappedTarget = target;
SimpleConfigurator.ConfigureForTargetLogging(asyncWrapper, LogLevel.Trace);

Related

Create Cascade Form via MDI at runtime via looping a list

I have a list that I use a foreach loop to create forms. I am trying to get the forms to cascade. I've been trying to use the MDI container and set the parent form if it meets a condition.
I would like to know if Child MDI forms can only be created inside the parent and not via a loop.
E.g
List<string> FormNames;
FormNames.add("Cat Group");
FormNames.add("Big Cats")
FormNames.add("Medium Cats")
FormNames.add("Small Cats")
Foreach(string Name in FormNames)
{
FormA NewForm = new FormA(Name);
if(NewForm.Name == "Cat Group") <--- This sets the ParentForm if conditions are met.
{
NewForm.IsMdiContainer = true;
NewForm.Layout(MdiLayout.Cascade);
}
else
{
NewForm.IsMdiContainer = false;
NewForm.MDIParent = <-----(what do I put here? I can't put NewForm or else it would reference itself.
}
NewForm.Show();
You just need the help of another variable of your Form. Set this variable to be the reference to the NewForm when you build the MDIContainer and then use it when you create the MdiChilds
List<string> FormNames = new List<string>();
FormNames.Add("Cat Group");
FormNames.Add("Big Cats");
FormNames.Add("Medium Cats");
FormNames.Add("Small Cats");
Form parent = null;
foreach (string Name in FormNames)
{
Form NewForm = new Form();
NewForm.Name = Name;
if (NewForm.Name == "Cat Group")
{
NewForm.IsMdiContainer = true;
parent = NewForm;
parent.LayoutMdi(MdiLayout.Cascade);
}
else
{
NewForm.IsMdiContainer = false;
NewForm.MdiParent = parent;
NewForm.Show();
}
}
parent.Show();

Codename One Picker text spinning after item is selected

I have a CN1 application that uses three pickers inside a container.
One of the pickers just contains small strings like "1x" , "2x" , etc.
Every time an item is selected on the running application, the selected text spins really fast, what looks kind of odd.
I have tried setting padding and margin to zero, and set SmoothScrolling to false.
picker.setSmoothScrolling(false);
All to no avail.
Is there ant solution to it? Many thanks in advance ..
Here is the relevant part of the code:
private final Picker pickerInterval = new Picker();
private final Picker pickerDayOrMonth = new Picker();
private final Picker pickerFinal = new Picker();
String stringPickerInterval = "repetir a cada ..";
pickerInterval.setType(Display.PICKER_TYPE_STRINGS);
pickerInterval.setUIID("DatePickerDialog");
pickerInterval.setStrings("1","2","3","4","5","6","6","8","9","10","11","12",stringPickerInterval);
pickerInterval.setSelectedString(stringPickerInterval);
pickerInterval.addActionListener((e) -> {
if (!pickerInterval.getSelectedString().equals(stringPickerInterval)) {
pickerInterval.setUIID("DatePickerDialogSelected");
} else {
pickerInterval.setUIID("DatePickerDialog");
}
});
String stringPickerDayOr = "dias ou semanas ou ...";
pickerDayOrMonth.setType(Display.PICKER_TYPE_STRINGS);
pickerDayOrMonth.setUIID("DatePickerDialog");
pickerDayOrMonth.setStrings("Dia(s)", "Semana(s)", "Mes(es)","Ano(s)" , stringPickerDayOr);
pickerDayOrMonth.setSelectedString(stringPickerDayOr);
pickerDayOrMonth.addActionListener((e) -> {
if (!pickerDayOrMonth.getSelectedString().equals(stringPickerDayOr)) {
pickerDayOrMonth.setUIID("DatePickerDialogSelected");
} else {
pickerDayOrMonth.setUIID("DatePickerDialog");
}
});
String stringPickerFinal = "freqüência das repetições ..";
pickerFinal.setType(Display.PICKER_TYPE_STRINGS);
pickerFinal.setUIID("DatePickerDialog");
pickerFinal.setStrings("1 x","2 x","3 x","4 x","5 x","6 x","6 x","8 x","9 x","10 x","11 x","12 x" , stringPickerFinal);
pickerFinal.setSelectedString(stringPickerFinal);
pickerFinal.addActionListener((e) -> {
if (!pickerFinal.getSelectedString().equals(stringPickerFinal)) {
pickerFinal.setUIID("DatePickerDialogSelected");
} else {
pickerFinal.setUIID("DatePickerDialog");
}
});
container = new Container(new GridLayout(1, 3));
container.setUIID("ContainerPicker");
container.add(pickerInterval).add(pickerDayOrMonth).add(pickerFinal);

How to get accessible camera resolutions?

I would like to ask, how it is possible to get all accessible camera resolutions in Windows Phone 8.1 app (for both silverlight and WinRT). I wanted to use:
Windows.Phone.Media.Capture.PhotoCaptureDevice.GetAvailableCaptureResolutions(
Windows.Phone.Media.Capture.CameraSensorLocation.Back);
But I am getting message that namespace Windows.Phone.Media.Capture is obsolete and may not be supported from next version of Windows Phone starting with Windows Phone Blue and that I should use Windows.Media.Capture instead. However Windows.Media.Capture does not allow me to get accessible camera resolutions, so I would like to ask, how to solve this.
Thank you.
It can be done like this:
First let's define method to get Device ID which will be used to take a photo:
private static async Task<DeviceInformation> GetCameraID(Windows.Devices.Enumeration.Panel desiredCamera)
{
DeviceInformation deviceID = (await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture))
.FirstOrDefault(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == desiredCamera);
if (deviceID != null) return deviceID;
else throw new Exception(string.Format("Camera of type {0} doesn't exist.", desiredCamera));
}
Then after we initialize the camera - we can read the resolutions like this:
private async void InitCameraBtn_Click(object sender, RoutedEventArgs e)
{
var cameraID = await GetCameraID(Windows.Devices.Enumeration.Panel.Back);
captureManager = new MediaCapture();
await captureManager.InitializeAsync(new MediaCaptureInitializationSettings
{
StreamingCaptureMode = StreamingCaptureMode.Video,
PhotoCaptureSource = PhotoCaptureSource.VideoPreview,
AudioDeviceId = string.Empty,
VideoDeviceId = cameraID.Id
});
// Get resolutions
var resolutions = captureManager.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.Photo).Select(x => x as VideoEncodingProperties).ToList();
// get width and height:
uint width = resolutions[0].Width;
uint height = resolutions[0].Height;
}

ArcGIS Runtime for wpf - PointDataSource mapTip

I have GraphicsLayer in my application and I use PointDataSource like itemsSource:
trackEntryPointDataSource = new PointDataSource();
trackEntryPointDataSource.DataSpatialReference =
new SpatialReference((int)CommonEpsgCodes.JTSKEN);
trackEntryPointDataSource.XCoordinateBinding =
new System.Windows.Data.Binding("XJTSK");
trackEntryPointDataSource.YCoordinateBinding =
new System.Windows.Data.Binding("YJTSK");
SimpleRenderer srd = new SimpleRenderer();
srd.Symbol = new SimpleMarkerSymbol()
{
Color = new SolidColorBrush(Colors.Yellow)
};
EntriesLyr.GraphicsSource = trackEntryPointDataSource;
EntriesLyr.Renderer = srd;
Have someone any idea how to add MapTips to graphics symbols?
GraphicsLayer class has a MapTip property.
A detailed example if found here

Selected item not showing in a WPF combobox

I'm creating a part of my window in code. For a combobox I do this:
ObservableCollection<ParamClassOption> options = new ObservableCollection<ParamClassOption>(
context.ParamClassOptions.Where(x => x.IDParamClass == val.CompTypeParam.IDParamClass));
ComboBox combobox = new ComboBox();
combobox.Name = "combobox" + val.CompTypeParam.ParameterName.Replace(" ", "");
combobox.ItemsSource = options;
combobox.SelectedValuePath = "IDParamClass";
combobox.DisplayMemberPath = "OptionName";
if (val.ParamClassOption != null)
{
combobox.SelectedValue = val.ParamClassOption.IDParamClassOption;
}
layoutitem.Content = combobox;
I'm able to select an item from the list and save it to the database. The problem that I have is to show the saved value again upon retrieving the values back from the database. Any idea why it's not showing? val.ParamClassOption.IDParamClassOption in the second to last line above has the correct value when the record is retrieved to be displayed.
i think you forgot to bind your selected value
var binding = new Binding {Path = new PropertyPath("IDParamClassOption"), Mode = BindingMode.TwoWay, Source = val.ParamClassOption};
combobox.SetBinding(ComboBox.SelectedValueProperty, binding);
hope this helps
Thanks for the help. I ended up using a completely different approach by adding the items to the combo-box one by one. I then set the selected item to previously added value (using the Text property). Here is what my code looks like now:
if (controlType == "Combobox")
{
ComboBox combobox = new ComboBox();
combobox.Name = "combobox" + val.CompTypeParam.ParameterName.Replace(" ", "");
ObservableCollection<ParamClassOption> options = new ObservableCollection<ParamClassOption>(
context.ParamClassOptions.Where(x => x.IDParamClass == val.CompTypeParam.IDParamClass));
combobox.Items.Clear();
foreach (ParamClassOption option in options)
{
ComboBoxItem item = new ComboBoxItem();
item.Content = option.OptionName;
combobox.Items.Add(item);
}
combobox.Text = val.ParamClassOption.OptionName;
layoutitem.Content = combobox;
}
Later when reading the value from the combobox to save to the database I did this:
ObservableCollection<ParamClassOption> option = new ObservableCollection<ParamClassOption>(
context.ParamClassOptions.Where(o => o.IDParamClass == value.CompTypeParam.IDParamClass).Where(o => o.OptionName == combobox.Text));
value.IDParamClassOption = option[0].IDParamClassOption;

Resources