Show a Dialog() or MessageDialog() from the MainWindow.cs? - mono

I'm trying to display a Dialog() or MessageDialog() from my MainWindow.cs (standard MainWindow.cs file that is created from the C# GTK# 2.0 Project template).
I'm getting a rather nasty error when using the below code:
public partial class MainWindow : Gtk.Window
{
public MainWindow () : base(Gtk.WindowType.Toplevel)
{
Build();
}
public void CreateAlert(string message)
{
Console.WriteLine(string.Format("CreateAlert() - message: {0}", message));
Dialog dialog = new Dialog("Error", this, Gtk.DialogFlags.DestroyWithParent);
dialog.Modal = true;
dialog.AddButton ("OK", ResponseType.Close);
dialog.Response += on_dialog_response;
dialog.Run ();
dialog.Destroy ();
}
}
I believe the cause of this error is the second param in the Dialog() constructor - "this". My question is... how does one satisfy the second param of "Window win" when inside the MainWindow.cs?
Thanks in advance.

Related

How to create multiple custom renderer with same type?

I wanted to create a page render with ContentPage type. I created so in android and it is working but in IOS there has custom page renderer with same type (ContentPage). It can be removed as this was from nuget package and working on different context.
Here is my code
[assembly: ExportRenderer(typeof(ContentPage), typeof(CustomPageRenderer))]
namespace AlwinInvoiceGenerator.IOS
{
using CoreGraphics;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
public class CustomPageRenderer : PageRenderer
{
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
if (Element == null || !(Element is ContentPage basePage) || basePage.BindingContext == null ||
!(basePage.BindingContext is BaseViewModel baseViewModel))
{
return;
}
SetCustomBackButton(baseViewModel);
}
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
OverrideUserInterfaceStyle = UIUserInterfaceStyle.Light;
}
private void SetCustomBackButton(BaseViewModel baseViewModel)
{
var fakeButton = new UIButton {Frame = new CGRect(0, 0, 50, 40), BackgroundColor = UIColor.Clear};
fakeButton.TouchDown += (sender, e) =>
{
baseViewModel.OnBackButtonClicked();
};
NavigationController?.NavigationBar.AddSubview(fakeButton);
}
}
It seems it not registering and that is why not calling.
I have another page renderer that is register in assembly
[assembly: ExportRenderer(typeof(ContentPage), typeof(IOSToolbarExtensions.iOS.Renderers.IOSToolbarExtensionsContentPageRenderer), Priority = short.MaxValue)]
If I removed this line then above code is working but not two in the same time.
Please help
Same type seems not working for multiple renderer.
I have created sub type of my custom renderer and override the methods which needed to. It is working well

Changing starting view in AvaloniaUI project

I want to change starting view. It displays MainWindow by default.
I created Start view with cli command and Start view model similarly to MainWindow files.
When I add lines:
<Design.DataContext>
<vm:StartViewModel/>
</Design.DataContext>
to Start.xaml file I get and error:
System.Xaml.XamlException: Exception has been thrown by the target of an invocation.
And when I try to replace MainWindow with Start in App file like this:
public class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new Start
{
DataContext = new StartViewModel()
};
}
base.OnFrameworkInitializationCompleted();
}
}
I get:
The type or namespace "Start "could not be found.
How can I make this work ?

XMessageControl UIMessage not working on monodroid

I am trying to change the way notifications are shown on my Xamarin.forms project and when adding the Softweb.Controls.UIMessage component it won't show either the message or toast.
UIMessage.ShowMessage ("Customization", "Hey! You Clicked on Button", MessageControl.MessageTypes.Warning, "red.png", Color.BrandRed, Color.Black, true, OnDissmissControl);
I running this code from a dependency controller, I was wondering if the error is caused by not having the right context, but I see not way to add one to the class. Has anyone try using this component on a Xamarin.forms project? (this is specific to MonoDroid).
The answer, just make sure you are running on the mainthread and it should work. This would have been much easier if the library had some documentation worth looking at.
[assembly: Xamarin.Forms.Dependency (typeof (.Android.MessageBar))]
namespace .Android
{
public class MessageBar : IMessageBar
{
public MessageBar ()
{
}
public void Show(MessageType messageType, string title, string message)
{
var context = Forms.Context;
Device.BeginInvokeOnMainThread (() => {
//CustomToast customtoast=new CustomToast(context, messageType, title, message);
UIMessage.ShowMessage ("Customization", "Hey! You Clicked on Button", MessageControl.MessageTypes.Warning, "validation.png", Color.BrandRed, Color.Black, true, OnDissmissControl);
});
}
public void OnDissmissControl()
{
}
}
}

Trying to make tables in mono develop

I just started using monodevelop and I am having a hard time to design the forms. I have understood the concept of widgets inside containes. I am trying to get a Table which is inside a scroll view. The Table should have 3 columns and I should be able to set the column names.
I have looked at some documentation by mono develop which shows how to use the Node View to do the same but I haven't been able to figure out why is it coming in a new window and how to get it on my first screen itself.Also is there any way I can drag and drop to the form to make my columns and table header? I have attached the code :
using System;
using Gtk;
namespace ImageCompressionTool
{
class MainClass
{
public static void Main (string[] args)
{
Application.Init ();
MainWindow win = new MainWindow ();
win.Show ();
Application.Run ();
Gtk.Application.Init ();
NodeViewExample win1 = new NodeViewExample ();
win1.Show ();
Gtk.Application.Run ();
}
}
public class MyTreeNode : Gtk.TreeNode {
string song_title;
public MyTreeNode (string artist, string song_title)
{
Artist = artist;
this.song_title = song_title;
}
[Gtk.TreeNodeValue (Column=0)]
public string Artist;
[Gtk.TreeNodeValue (Column=1)]
public string SongTitle {get { return song_title; } }
}
public class NodeViewExample : Gtk.Window {
Gtk.NodeStore store;
Gtk.NodeStore Store {
get {
if (store == null) {
store = new Gtk.NodeStore (typeof (MyTreeNode));
store.AddNode (new MyTreeNode ("The Beatles", "Yesterday"));
store.AddNode (new MyTreeNode ("Peter Gabriel", "In Your Eyes"));
store.AddNode (new MyTreeNode ("Rush", "Fly By Night"));
}
return store;
}
}
public NodeViewExample () : base ("NodeView")
{
SetSizeRequest (200,150);
// Create our TreeView and add it as our child widget
Gtk.NodeView view = new Gtk.NodeView (Store);
Add (view);
// Create a column with title Artist and bind its renderer to model column 0
view.AppendColumn ("Artist", new Gtk.CellRendererText (), "text", 0);
// Create a column with title 'Song Title' and bind its renderer to model column 1
view.AppendColumn ("Song Title", new Gtk.CellRendererText (), "text", 1);
view.ShowAll ();
}
}
}
Kindly help me out. Thanks!
If you only want your NodeView window to be displayed then remove the code that is showing the MainWindow. Your Main method is currently showing two windows. If you just want it to show your NodeViewExample window then it should look like:
public static void Main (string[] args)
{
Gtk.Application.Init ();
NodeViewExample win1 = new NodeViewExample ();
win1.Show ();
Gtk.Application.Run ();
}
You cannot drag and drop columns into a Gtk.NodeView or Gtk.TreeView into the designer.

How to display a Labels 'Error on ErrorProvider1'

Goal
I want to display the text that I put in the Label's "Error on ErrorProvider1" attribute whenever I get an error. See the following label's attributes below.
I try to display the text in the red rectangle into my ErrorProvider1 SetError(control, value) function.
If TextBox1.Text.Trim.Contains("'") Then
ErrorProvider1.SetError(lblErr, ErrorProvider1.GetError(lblErr))
Else
ErrorProvider1.SetError(lblErr, "")
End If
How can I retrieve the 'Error on ErrorProvider1' text from the lblErr to display it in the ErrorProvider1 SetError value?
The ErrorProvider component is very awkward to use effectively. It is fixable however, I'll give an example in C# that extends the component with some new capabilities:
ShowError(Control ctl, bool enable) displays the text that you entered at design-time when the enable argument is true. The easier-to-use version of SetError().
HasErrors returns true if the any active warning icons are displayed. Handy in your OK button's Click event handler.
FocusError() sets the focus to the first control that has a warning icon, if any. It returns false if no warnings are remaining.
SetError() is a replacement of ErrorProvider.SetError(). You only need it if you add any controls after the form's Load event fired or if you need to modify the warning text.
Add a new class to your project and paste the code shown below. Compile. Drop it from the top of the toolbox onto the form. The design-time behavior is identical. Modestly tested.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.ComponentModel.Design;
class MyErrorProvider : ErrorProvider {
public void ShowError(Control ctl, bool enable) {
// Easy to use version of SetError(), uses design-time text
if (!enable) base.SetError(ctl, "");
else {
if (errors.ContainsKey(ctl)) base.SetError(ctl, errors[ctl]);
else base.SetError(ctl, "No error text available");
}
}
public bool HasErrors {
// True if any errors are present
get {
foreach (var err in errors)
if (!string.IsNullOrEmpty(base.GetError(err.Key))) return true;
return false;
}
}
public bool FocusError() {
// Set the focus to the first control with an active error
foreach (var err in errors) {
if (!string.IsNullOrEmpty(base.GetError(err.Key))) {
err.Key.Focus();
return true;
}
}
return false;
}
public new void SetError(Control ctl, string text) {
// Use this only to add/modify error text after the form's Load event
if (!string.IsNullOrEmpty(text)) {
if (errors.ContainsKey(ctl)) errors[ctl] = text;
else errors.Add(ctl, text);
}
base.SetError(ctl, text);
}
private void initialize(object sender, EventArgs e) {
// Preserve error text
copyErrors(((Form)sender).Controls);
}
private void copyErrors(Control.ControlCollection ctls) {
foreach (Control ctl in ctls) {
var text = this.GetError(ctl);
if (!string.IsNullOrEmpty(text)) {
errors.Add(ctl, text);
base.SetError(ctl, "");
}
copyErrors(ctl.Controls);
}
}
private Dictionary<Control, string> errors = new Dictionary<Control, string>();
// Plumbing to hook the form's Load event
[Browsable(false)]
public new ContainerControl ContainerControl {
get { return base.ContainerControl; }
set {
if (base.ContainerControl == null) {
var form = value.FindForm();
if (form != null) form.Load += initialize;
}
base.ContainerControl = value;
}
}
public override ISite Site {
set {
// Runs at design time, ensures designer initializes ContainerControl
base.Site = value;
if (value == null) return;
IDesignerHost service = value.GetService(typeof(IDesignerHost)) as IDesignerHost;
if (service == null) return;
IComponent rootComponent = service.RootComponent;
this.ContainerControl = rootComponent as ContainerControl;
}
}
}
Your issue is that you are replacing the error message when nothing is wrong. As noted in your comment below, you are storing the localized error message in the label's Tag, so you can do the following:
If TextBox1.Text.Trim.Contains("'") Then
ErrorProvider1.SetError(lblErr, lblErr.Tag)
Else
ErrorProvider1.SetError(lblErr, "")
End If
You were correct to use ErrorProvider1.GetError(Control) to get the value. It's just that you're more than likely replacing it with an empty string before you were retrieving it.