The scenario is that I have text box which I put there URL when the user
type the url and press go I call to the service in TPL ,when the service
is loaded I need to enable the next button(Im working on wizard) if I dont use TPL IsServicevalid get true(bind to command)and the next button is enabled .but in task(TPL) the data is loaded and the next is disabled (even if I put it in the continue) I have noticed that if I click on the page with the mouse anywhere the next turn to enable,do you face some issue like this before?
even if the next button is disabled and I click on it it turn to enable ,all of this happen
just when I use task ,any idea?
this is strange ...:(
Task.Factory
.StartNew(() =>
{
//-----get service Data ---------
try
{
GetUsersData();
}
catch (Exception e)
{
_isValid = false;
ThrowErrorMessage(e.Message);
}
})
.ContinueWith((task) =>
{
Mouse.OverrideCursor = null;
}, System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
isServiceValid = true;
Sometimes the CanExecute state of commands won't be reflected on the ui untill you click on it.
I don't know why this happens, I personally think this is a behavior that should be changed in the framework itself if possible.
However you can force an update by calling
System.Windows.Input.CommandManager.InvalidateRequerySuggested();
Related
The code:
StartOperation = ReactiveCommand.CreateFromObservable(() => Observable.Start(() =>
{
SelectedOperation.State = OperationState.ACTIVE.ToString();
checkboxService.SaveChanges();
}));
results in binding handlers in being invoked seemingly randomly, whereas:
StartOperation = ReactiveCommand.Create(() =>
{
Interactions.Confirm.Handle(new MessageBoxArguments { CanCancel = false, IsWarning = false, Message = "Operation started!", Title = "Success" }).Subscribe(x =>
{
SelectedOperation.State = OperationState.ACTIVE.ToString();
checkboxService.SaveChanges();
});
});
Works perfectly. I assume this is to due with scheduling, but I would have thought that in both cases the code would be scheduled to run in the same way, except in the second example, a message box is shown first. Maybe the delay makes things work correctly?
The project is Winforms (I know) on .Net Standard and ReactiveUI is 17.1.50.
I would be very happy for some pointers here!
So it turns out that the reason it worked in the second example was not because of scheduling, but rather because showing the MessageBox, forced the UI to update events.
The reason this is needed, is because the button triggering StartOperation, is also affected by SelectedOperation.State being updated (the Enabled property is dependent on this) and it seems the flow is like this:
Clicking triggers StartOperation (OnClick)
This then updates SelectedOperation.State
This triggers various bindings, finally leading to an update of the Enabled property
This is not working well/predictably, because the button is in some kind of transition state firing events and so on.
The solution in short, is to make sure that Application.DoEvents() is called somewhere in that chain, forcing the button out of whatever state it's in.
Consider I am having a button called "Add" and is bind with the command "AddBtnExceuteCommand".
Consider Execute() method of this Command having very large and time consuming calculations.
I am developing a tool which will save the Actions like Click, Entering text into textbox etc. When I play it back the same actions will executed automatically.
consider I started recording actions. Lets say I have Clicked on Button called "Add". this click actions will save in some file called "Actions.xml". When I Started playing back that saved action by reading "Actions.xml" file. I have only Control over the Button not on the code behind of that button(means I do not have access to the AddBtnExceuteCommand command).
My Actions.Xml have lot of such actions which will be executed serially.
What I want===>
When I started Reading Actions.xml that will execute saved Actions(Clicks) automatically without considering whether the Code behind of button is executed or not. I want to Restrict the execution of second action unless The code behind of first Button is executed. So to do that I need to know whether the Code behind for that button click is executed or not. I am not having access to the code behind. I have controls(this is not wpf Controls) on Button.
I have Used White TestStack framework to get the control of Windows controls(like Button)
My UI may be Responsive while button click method performing lengthy calculations. UI might be on different thread.
So is it possible to check whether the code behind for that button click is executed or not. I wanted to check it only from button control.
Thanks.
Basically you are telling you having two logics:
Logic for the click
Logic for "enabling" the button
I guess you need to use a RelayCommand from the GalaSoft.MvvmLight.Command (please check this URL on how to install and this one on how use it).
Basically, you just bind your command in the view:
<Button Command="{Binding StoreActionCommand}"/>
And in the ViewModel ("code behind"), you specify two different actions: one is what the button do, and the next one is if this code can be executed.
You need to add this to the constructor of your ViewModel:
// declare your public attribute (it can be a property too if you want)
public ICommand StoreActionCommand;
// and on your ViewModel constructor
StoreActionCommand = new RelayCommand(StoreCommandExecute, CanStoreCommand);
private void StoreCommandExecute()
{
// here you add actions to your queue
}
private bool CanStoreCommand()
{
// here, you can check if your queue is empty or not..
return true;
}
If you want to add items, do you need to store it on an XML? Could it be just memory based? You could use a Queue for it.
For the background Thread, I would advise you to start working with the Task library. Besides being easier to understand, it is easier to control it. And never from your background thread try to interact with the UI. you can do it with some thread synchronization, but I would not recommend it. If you are doing something in the background, let it only do something and then return. Otherwise, use the IProgress classes to notify changes in the UI.
EDIT
I still note sure if that's what your looking for, but I'll try to help you again.
I usually do that do notify the UI when I have to do a background task notifying changes to the UI. You can use the IProgress to change some properties that are used by your UI. Note that you do not change the UI directly.. never! You just need to make a set of properties that do that for you.
First, create some properties so that your UI can connect to them:
private string executionStatus = string.Empty;
public string ExecutionStatus
{
get { return executionStatus; }
set
{
executionStatus = value;
RaisePropertyChanged(nameof(ExecutionStatus));
}
}
private bool canRun = true;
public bool CanRun
{
get { return canRun; }
set
{
canRun = value;
RaisePropertyChanged(nameof(CanRun));
}
}
Then, change the StoreActionCommand and CanStoreCommand to something like:
private bool CanStoreCommand()
{
return CanRun;
}
// note the async here
private async void StoreActionCommand()
{
CanRun = false;
// notification
var progressNotification = new Progress<string>((value) => ExecutionStatus = value);
// real background thread goes here, without blocking the UI
await Task.Run(() => {
DoWork(progressNotification);
});
CanRun = True;
}
private void DoWork(IProgress<string> progress)
{
progress.Report("Starting...");
try
{
progress.Report("doing x...");
progress.Report("doing y...");
}
catch(Exception err)
{
progress.Report(err);
}
progress.Report("Process finished");
}
Hope this helps you.
If you have to work on more items, you could control the CanRun as you want.
Another interesting stuff is that you could create a Model class in order to send more than just a string (you can pass a status and a flag indicating the possibility of the user to click the CanRun button during the work, but then a new Thread would be fired in parallel do the one that is already running).
I am building a document management system currently and I was trying to change the cursor to a "waiting" cursor while the document is loading, pretty standard.
As per the MSDN documentation, I am using the following code:
System.Windows.Input.Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait;
try
{
newPage.LoadForm(data);
}
finally
{
System.Windows.Input.Mouse.OverrideCursor = null;
}
The problem is, after LoadForm is finished, the cursor doesn't return to its normal state. I have debugged the program and the "null" line is being run so I have no idea what the problem is.
Any ideas?
If this is a long-running operation, you might consider moving this whole code to a Task (though in that case you'd have to dispatch the changes to the OverrideCursor property back to the main thread).
I tested this quickly with a Sleep simulating a long-running application and it seemed to work fine (I put this code in the window's constructor in an empty WPF application for testing).
Task.Factory.StartNew(() =>
{
Application.Current.Dispatcher.Invoke(() =>
System.Windows.Input.Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait);
try
{
Thread.Sleep(5000);
}
finally
{
Application.Current.Dispatcher.Invoke(() =>
System.Windows.Input.Mouse.OverrideCursor = null);
}
});
WORKAROUND
You must set it to the cursor type you want instead of setting it to null. So, instead of setting it to null, set it to Arrow (I assume that is what you would want in Normal state).
So in finally block replace your code with this:
System.Windows.Input.Mouse.OverrideCursor = System.Windows.Input.Cursors.Arrow;
EDIT 1:
Try setting the Cursor to null at the end of try block if in case you do not want to use the workaround.
How can I solve this error?
"The requested resource is in use. (Exception from HRESULT: 0x800700AA)".
This appears while navigating to a different website using the WebBrowser control in C# .NET. Why?
The WebBrowser control is considered "in use" if either a navigation action is currently being processed, or any blocking dialog from the control is currently open (including context menu, Javascript alerts, NTLM login dialog, etc.). You can use the WebBrowser.IsBusy property to detect these states.
If due to a currently incomplete navigation action, you could try to stop the current navigation (if you indeed want to stop when the page is not completed loaded) or add the new navigation to a request queue and use a timer to wait until WebBrowser.IsBusy returns false.
If instead the busy state is due to one or more open blocking dialogs, you could do the same wait technique and perhaps Messagebox.Show() the user a message that pending navigation is delayed due to an open dialog window.
I had this same issue. Calling WebBrowser.Stop() did not help, and WebBrowser.IsBusy never became false.
It turns out that if the page creates any sort of dialog (alert() popups, javascript errors, NTLM login popups etc.) you can't navigate away from the page until the dialog is closed.
My solution was to prevent the dialogs from showing in the first place. Apparently preventing all of these popups is simple; just set
webBrowser.ScriptErrorsSuppressed = true;
bool go = false;
string SiteContent1 = string.Empty;
string SiteContent2 = string.Empty;
int index = 0;
WebBrowser wb = new WebBrowser();
void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
try
{
if (go)
{
SiteContent2 = wb.DocumentText;
// Code to compare to contents of the webbrowser
index++;
go = false;
steps = 1;
}
if (!go)
{
if (index >= TotalSiteCount)
{
Stop();
}
else if (steps == 1)
{
wb.Navigate(UrltocompareList[index].Url1);
}
else if (steps == 2)
{
SiteContent1 = wb.DocumentText;
wb.Navigate(UrltocompareList[index].Url2);
go = true;
}
steps++;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
UrltocompareList is a collection of 2 sites to compare.
TotalSiteCount is the number of items in UrltocompareList.
The form for this inherit IOleClientSite to remove media such as images, videos and no active X download to have a faster rendering time in webbrowser control.
I use this method instead of system.net.webclient to get the html of a webpage then compare them.
I got this error when it hits the wb.Navigate method.
An issue I ran into when running specflow tests with watin in windows 10 is that win10 by default uses MS Edge, so I had never opened IE, and when watin started it IE was stuck on the prompt for using default settings. Selecting options, closing browser and running tests again worked for me.
Just something to watch
This can be solved pretty easily.
This error occurs when the browser commits an action while he's already performing an action.
For example, you are navigating to some website while you rightclick in the web browser.
To solve this, I did the follow:
//if my webbrowser isn't performing any actions
if(!myWebBrowser.IsBusy)
{
//Navigate
myWebBrowser.Navigate("http://www.google.com");
}
First Try
1- Please Check Navigate URL's (if you check, please check again compiled folder)
2- Delete WebBrowser Control and Add New
Me forget copy original file App.Path + "\error.html" and see this problem.
Guarantee Method
I Fix This Error in VB6
Add WebBrowserControl wb(0) (Name wb , Index=0)
And Before Ever Navigate
For i = 1 To wb.UBound
Unload wb(i)
Next
Load wb(1)
wb(0).Visible = False
wb(1).Visible = true
wb(1).Navigate URL
I have a try-catch statement in reference to downloading a file. When the file is downloaded, I then enable one of my menu items then turn off a timer set to retry the download in one minute.
My problem is that for some reason my trafficManagementToolStripMenuItem.Enabled = true; line is activating the catch statement even though the menu item is being enabled. The file correctly downloads and when I comment out that line, it works perfectly. But every time I run it, I get the "error" message box and the timer is not disabled even though the menu item correctly enables after the download is complete.
Any ideas?
try
{
////downloads Data
string address = "http://website.file.txt";
string filename = "vsd.txt";
WebClient client = new WebClient();
client.DownloadFile(address, filename);
trafficManagementToolStripMenuItem.Enabled = true;
timer1.Enabled = false;
}
catch
{
timer1.Enabled = true;
MessageBox.Show("error", "test");
}
You don't say what the exception is, but I'd guess that you're running your download routine in a background thread, is that right? You can only access controls from the thread that created them: the main UI thread. Accessing a control such as a ToolStripMenuItem from a background thread will cause an exception.
If this is the case, use the Control.Invoke or Control.BeginInvoke method to run the .Enabled = true call on the ToolStripMenuItem's thread. To do this, you'll need a Control (unfortunately ToolStripMenuItem is only a Component). I'll assume you can get a reference to the containing Form from somewhere. Now you can write this:
Action enableAction = delegate() { trafficManagementToolStripMenuItem.Enabled = true; }
form.BeginInvoke(enableAction);
This causes the enableAction to run on the correct UI thread for form.
change your catch to be
catch (Exception ex)
{
timer1.Enabled = true;
MessageBox.Show("error", ex.Message);
}
This will at least give you the actual error message.
I'm guessing it's because you are not running in the UI thread and need to use Control.Invoke, take a look at http://msdn.microsoft.com/en-us/library/system.windows.forms.control.invokerequired.aspx on msdn