I recently made a custom ribbon in Sitecore. The two buttons in it fire off a command which activate a Xaml application using SheerResponse.ShowModalDialog. These applications effect the state of a database being read by another component on the ribbon.
I either need to be able to fire a custom event or function from the Xaml application to make the other ribbon component, or I need to be able to make the component on the ribbon aware that it needs to re-render when the ModalDialogs close. I don't see any obvious events which would do this, and I've gone about as far as I can when looking through the raw code with DotPeek and I haven't seen anything which even looks promising.
Apparently, the answer was there the whole time and I had missed it.
SheerResponse has a five parameter version of ShowModalDialog which accepts a boolean as a final parameter. This means I can couple it with ClientPage.Start:
Context.ClientPage.Start(this, "Run", kv);
}
private void Run(ClientPipelineArgs args)
{
var id = args.Parameters["id"];
if(!args.IsPostBack)
{
string controlUrl = string.Format("{0}&id={1}", UIUtil.GetUri("control:AltDelete"), id);
SheerResponse.ShowModalDialog(controlUrl,"","","",true);
args.WaitForPostBack();
}
else
{
Logger.LogDebug("post back");
}
Logger.LogDebug("out of if");
}
Related
I have this code to check if a service is active, but I would like to know if there is any way for an EditText to show the status of the service, without making this query per second, or in a separate thread, or linking it in some way? that it is possible to detect if the service stopped
private bool MiServicioEstaCorriendo(Class #class, Context contexto)
{
ActivityManager manager = (ActivityManager)contexto.GetSystemService(Context.ActivityService);
foreach (ActivityManager.RunningServiceInfo service in manager.GetRunningServices(Integer.MaxValue))
{
if (#class.Name.Equals(service.Service.ClassName))
{
Log.Info(typeof(BroadcastGps).Name, "MiServcicioEstaCorriendo: true");
return true;
}
}
Log.Info(typeof(BroadcastGps).Name, "MiServcicioEstaCorriendo: false");
return false;
}
You are basically in need of a way to pass events/messages among classes within your application. So this question probably goes down to Android & C# implementation of such a pattern. Xamarin.Forms has a MessagingCenter class, but since you are using Xamarin.Native, you would have to create something yourself
There's nothing actually already baked in to Android or C#, but so you can implement one of the most common ways to let a class spread an event/message using the "Listener" (term used in Android) or "Delegate" (term used in C#) technique.
There are frameworks too like PubNub that you can use as Nuget packages that simplify everything for you.
Some more resources to understand the concept: Wikipedia, IBM.
And Some Android resources: Handlers, AsyncTasks, Parcelables.
Don't forget that your event to update your EditText may not be fired on the Main UIThread so you won't be able to see the changes unless you force that update line to be Run on UI Thread.
My question is: How do I add a windows context menu item for a specific application, not globally?
Quick Brief:
We use Access (groan) for our CRM system. We use a basic 'copy to local' process for multi-access. I have written a C# 'launcher' of which handles this much better than a .bat file (they click the launcher, the launcher downloads the db, launches the db and quits). I also currently use a C# console application to handle development, automating stuff like incrementing version number, moving files around etc.
My Question/Goal:
I want to combine the two programs into one but I don't want to hinder the launcher from it's main purpose by jarring the user asking if they want to develop or not. I use this launcher too as I am primarily an estimator, hence wanting to combine the two. I have read that you can add context menu items to Windows as a whole, but I want to be able to add a launch option into the context menu just for this application. i.e. right click on program, normal menu options but with the addition of "Development Mode", this opens the program with arguments that I can use to open the development window/console instead.
Things to note:
I have played around with holding a key on start but it can be vague when to press the key. Too early - you will end up typing "r" several times into the active window, too late - and it will miss the capture point.
I have also looked at having a button on the launcher that gives you the option to go into dev mode, but the launcher is only open for around a second so its really easy to miss.
Thanks in advance
EDIT: The launcher is made and run as a click-once app.
I dont really know about whether its possible to have a custom context for a specific program, as far as i know the context works with the extension. That being said, i think there are better ways to handle your problem. Have a look at this
static void Main(string[] args)
{
/* here normal flow of the launcher*/
if (args[0] == "-dev")
{
/*here de developer mode*/
Console.WriteLine("Developer mode activated");
}
}
The way to use it is simple, you make a shorcut, and where it says the shorcut target you will have something like this "C:\Users****\Documents\visual studio 2017\Projects\Test\Test\bin\Debug\Test.exe" and you should change it to something like this "C:\Users****\Documents\visual studio 2017\Projects\Test\Test\bin\Debug\Test.exe" -dev
Further to this I stumbled upon some code to make this work. Hopefully this will help someone in the future. I am doing this in WPF, but I am sure you could probably adapt this code to work elsewhere.
1) App.xaml - Adding the JumpList action
After (not inside) the Application.Resources property add the following and change to your liking (There are a lot of properties I haven't used for development sake, check out the link to learn more):
<Application.Resources>
...
</Application.Resources>
<JumpList.JumpList>
<JumpList ShowRecentCategory="False"
ShowFrequentCategory="False">
<JumpTask Title="Open Dev Mode"
Description="Use this to enter dev mode (admins only)"
Arguments="DevMode:true"/>
</JumpList>
</JumpList.JumpList>
This will create a "Task" in the jump list:
2) Create Global static class - this will allow you to store the variable for later use in other forms.
public static class Global
{
public static Boolean DevMode = false;
}
3) App.xaml.cs - Adding OnStartup handler
Inside the App class create an override method for OnStartup
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
Global.DevMode = Boolean.Parse(e.Args.FirstOrDefault().ToString().Split(':')[1]);
}
}
4) Read the variable in your form using Global.DevMode
private void Window_ContentRendered(object sender, EventArgs e)
{
if (Global.DevMode) RunYourDevScript();
}
As per a suggestion in a comment, that has gone for some reason. I am going to revert to keypress but use shift instead or "R".
Failing this, or if it causes problems it will look at creating a global context menu item for all programs, and just won't click it when I don't need to
Issue
I am running tests using the Coded UI Test builder and writing all the code from scratch. The issue I am facing is in the middle of the test there is a popup message with the results "Stay on this page" or "Leave this page". I want my test to be able to click "Stay on this page".
The popup sometimes appears straight after the event or sometimes appears a couple of seconds later.
Code
So the event that I run before the message appears is a button click:
ClickButton(browser, "login");
void ClickButton(UITestControl parent, string id)
{
var button = new HtmlButton(parent);
button.SearchProperties.Add(HtmlButton.PropertyNames.Id, id);
Mouse.Click(button);
}
I have tried Keyboard.SendKeys() but this just sends the keys to the browser window. I have also tried using the recording tool. Both are unsuccessful.
After this event I need to wait for the popup to appear and click "Stay on this page". Does anyone know how to achieve this?
We actually mapped this confirmation window and it works for us.
We start with a Window with name = Windows Internet Explorer
Followed by a Pane with name = Windows Internet Explorer
and finally with a Button of name Stay on this page
All with Technology = MSAA.
You must handle writing code to wait for readiness of the control and proper time out if you don't expect the confirmation every time.
Hope this helps.
Depending on what exactly that window is, you should be able to deal with it no problem. I would use the inspector to get the properties of the window and use one of the WaitFor* methods to give it some time. Here is an example of dealing with the security pop up that IE shows:
namespace CaptainPav.Testing.UI.CodedUI.PageModeling.Win
{
public class IESecurityWindow<T> : PageModelBase<WinWindow>
{
protected const string SecurityWindowName = "Internet Explorer Security";
internal protected override WinWindow Me => new WinWindow().Extend(WinWindow.PropertyNames.Name, SecurityWindowName, PropertyExpressionOperator.EqualTo);
protected WinButton AllowButton => this.Me.Find<WinButton>(WinButton.PropertyNames.Name, "Allow", PropertyExpressionOperator.EqualTo);
internal readonly T AllowModel;
public IESecurityWindow(T allowModel)
{
this.AllowModel = allowModel;
}
public T ClickAllow()
{
// if not IE, this will return false and the next model is returned; change the time if you need more or less wait
if (this.AllowButton.IsActionable(3000))
{
Mouse.Click(this.AllowButton);
}
return AllowModel;
}
}
}
In this case, the dialog is a Win* type, not Html*. There are some custom extension methods sprinkled in to make the searching and stuff easier, but this should give you an idea. If interested, the extensions (which are written by me) can be found on github.
In a program that I'm testing with Coded UI Tests, I've got a window that opens for only a second or so, and I want to verify that this window is opening.
Is there a way to freeze the program, or make it run slow so that the test is able to find that window?
As I already mentioned in my comment there isn't much (perhaps nothing) you can do by the CodedUi Test to catch the window, since this functionality is built into the application.
My suggestion is to make this property configurable. Some of the properties in the applications under test need to be configurable so it can be tested. Consider the following requirements:
The service is restarting every month.
The user is deleted after one year of inactivity.
How would you test them? Will you wait a month or a year to go by? Those kind of parameters have to be available for the Qa team, otherwise they cannot be tested. I know that with this approach you have to do changes to your app's code and build but I think is the only way to solve it.
How about adding a Thread.Sleep(100);
http://msdn.microsoft.com/en-us/library/d00bd51t
From what I understand, the best approach is to break up your tasks as small as possible. So for a UI test I did that opens a shortcut on my toolbar, clicks login on a popup within, then clicks a tab in the application, the code looks like this:
namespace CodedUITestProject1
{
/// <summary>
/// Summary description for CodedUITest1
/// </summary>
[CodedUITest]
public class CodedUITest1
{
public CodedUITest1()
{
}
[TestMethod]
public void CodedUITestMethod1()
{
// To generate code for this test, select "Generate Code for Coded UI Test" from the shortcut menu and select one of the menu items.
// For more information on generated code, see http://go.microsoft.com/fwlink/?LinkId=179463
this.UIMap.OpenWindow();
this.UIMap.ClickLogin();
this.UIMap.ClickDevelopment();
}
//snip
}
So then in the ClickDevelopment() method, I know that the program should be visible, so rather than just dive right into the method actions, I can throw a Thread.Sleep() to make it visible for a little while longer.
public void ClickDevelopment()
{
Thread.Sleep(10000);
#region Variable Declarations
WinClient uIDevelopmentClient = this.UIQualityTrack30Window.UIItemWindow.UIQualityTrack30Client.UIDevelopmentClient;
#endregion
// Click 'Development' client
Mouse.Click(uIDevelopmentClient, new Point(39, 52));
}
Use Playback.Wait(2000) instead of Thread.Sleep(2000);
Best possible method is to add polling mechanism.
As soon as you perform the action which will open the window, call a function which will keep checking whether the window appeared for say, 1 min or so.
Be sure to call this function as soon as you perform action.
So even if the window stays for 500 millisecond, the info will be captured.
We have done similar thing in our project.
It has been a long question, so here is the summary first,
I have a Client class for my messenger project.
My Client class has a Socket.
I use its BeginReceive method to get messages from server.
In async callback of BeginReceive, I get the message using EndReceive.
When I get the message, I fire the MessageReceived event with message itself.
I use this Client class in my message form.
In message form, I can get the received message by attaching a method to Client.MessageReceived.
I use OnMessageReceived method for this purpose.
When I get the message, I can show it on a TextBox (using Control.Invoke) or MessageBox.
I can also add a new tab to my TabControl in OnMessageReceived.
When I try to initialize a WebBrowser control, I get ThreadStateException.
The control I use to display messages derives from WebBrowser control, so I need it.
Threading.Thread.CurrentThread.ThreadState is "Background".
I don't think you'll need the details but you can find the detailed question I first intented to post below.
Many thanks.
I'm working on a messenger project (Server is a Windows Service and Client is a Windows Forms Application) using Net.Socket's async methods.
I fire Client's MessageReceived event in callback of Socket.BeginReceive;
Everything is how I want them to be until here.
I use MessageReceived event in my form (the one that two people writes to each other) I can do anything I want to the UI using Control.Invoke method (if required) with one annoying exception.
I have tabbed conversations in the form so when a message arrives, I check if there is an open conversation (tab) with the sender. If yes, I select that tab and display the message. If no, I create a new ConversationTab.
Now, I'm sorry if it's being a long question than it should be or if I can't explain myself sufficently. English is not my first language and this is my first question in Stack Overflow.
So, here is the ConversationTab:
public class ConversationTab : TabPage
{
public User Friend { get; private set; }
public MessageBrowser MessageBrowser { get; private set; }
public ConversationTab(User friend) : base(friend.DisplayName)
{
Friend = friend;
MessageBrowser = new MessageBrowser();
Controls.Add(MessageBrowser);
MessageBrowser.Dock = DockStyle.Fill;
}
}
MessageBrowser derives from WebBrowser and the reason I use this is because I could not apply custom styles (color, font, size) 'per message' using RichTextBox. RichTextBox.SelectedColor doesn't always work or I couldn't make it work as intended. MessageBrowser let's me use CSS instead. Wandering off of the subject? Sorry.
Here is the NewConversation method I call when MessageReceived event fires:
public void NewConversation(User friend)
{
ConversationTab tab = Conversations.FirstOrDefault(c => c.Friend.Id == friend.Id);
if (tab != null)
ActiveConversation = tab;
else
{
tab = new ConversationTab(friend);
// add tab to TabControl
}
// bla
}
"Conversations" gets the tab pages of the TabControl and "ActiveConversation" gets or sets the SelectedTab property of the TabControl.
My point in creating these properties are mostly thread-safety logic inside.
So the question: It's throwing ThreadStateException in "tab = new ConversationTab(friend)" part of the above code. It is the "MessageBrowser = new MessageBrowser()" part of the first code and the constructor of MessageBrowser. The reason of why I didn't provide MessageBrowser's constructor code is because the exception is thrown before any line of inner code gets executed (It is about WebBrowser's constructor, I get this exception when I try to initalize a WebBrowser, too.)
Actually I don't even get an exception, the application just closes there without notifying me about anything. I saw the exception when I try to call "MessageBrowser = new MessageBrowser()" on ConversationTab's constructor in Watch window.
I'm kind of new to using threads and asynchronous methods.
MSDN says:
ThreadStateException is thrown by methods that cannot perform the requested operation due to the current state of a thread.
In my case, the thread's state is "Background".
I have no clue about what am I doing wrong.
Thank you very much if you read the whole thing and thank you much more if you can help.
This seems to be related to using COM (web browser control uses COM) in .NET where thread apartment needs to be set to STA.
Try adding [STAThread] to your entry point.
Have a look at this.