I have a style/good code question. It's one of those "not that important because it's working" things but still, I'd like some insight from the community. I'm in C# but the methodology could apply to anything OOP
So I have a class, it's essentially a container for data. I pass the class to the database instead of passing 10 parameters. The database writing class drops each data member into it's respective SQL parameter and executes the stored procedure in my database.
My question is, when I am collecting data into the class I have all of them attached to Change events. Like
private void chkIce_CheckedChanged(object sender, EventArgs e)
{
CheckBox chk = (CheckBox)sender;
if (chk.CheckState == CheckState.Checked)
outTruck.setWeather(2, true);
else
outTruck.setWeather(2, false);
}
and
private void txtTrailer_TextChanged(object sender, EventArgs e)
{
TextBox txt = (TextBox)sender;
newRecord.TrailerNumber = txt.Text.ToString();
}
This goes in and sets the ice value of my class to true/false based on what the user selects. Or sets the text. It's pretty straightforward, but there is a bit of code overhead as in each control has it's own event (also the cast on sender line might be overkill). The other way would be to collect all the data at submit. Drop it all into the class then. There was something else called entity framework and ORM, but I am at the moment stuck in .NET 3.5(we are with the times) and I've read that does not apply until you get to 4.0. I've not really read if there is a standard, it seems to be more preference than anything. So, fellow stack overlowieans...what are your thoughts?
Since it looks like you're in a web page with post back, I think it's easier to have that submit button handler functions where you instantiate your object, and manually set each property to the value of its corresponding UI element. Doing the data setting on every event handler (selection changed, focus out, etc.) would require the entire page to reload. (Then, you would have to persist that object across those post backs - a tedious and error prone feat, though doable.)
Even in a desktop project, I would collect all of the values from all UI elements to build my object, in that submit button's event handler.
You would want to implement event handlers on certain UI elements if the change of state in that UI element will affect something other than the object itself. For example, a checkbox may determine whether or not the user will be able to submit - because checking it so might add a feature that costs more where the total price of their order might exceed their current balance. This is when you would check to see whether the submit button should remain enabled or become disabled.
Related
In my app, when a user has made changes to the data on one page of my notebook control, I want to prompt them to save or discard their changes when they switch to a different page. I have bound the EVT_BOOKCTRL_PAGE_CHANGING event for this, and have created a handler method.
However, I can't tell what page the user is switching to. According to the wxBookCtrlEvent docs,
under Windows, GetSelection() will return the same value as GetOldSelection() when called from the EVT_BOOKCTRL_PAGE_CHANGING handler and not the page which is going to be selected.
Is there a workaround?
I guess as a workaround, you could use a mouse handler checking for when the left button is clicked. In a handler for that event you could do a hit test to see where the click was made and store the value of the tab that was clicked. Something like this:
void MyFrame::OnLeftDown( wxMouseEvent& event )
{
long flags;
int ht = m_notebook1->HitTest( wxPoint(event.GetX(),event.GetY()), &flags);
if( (flags & wxBK_HITTEST_NOWHERE) == 0 )
{
//store the value of ht somewhere
}
event.Skip();
}
void MyFrame::OnNotebookPageChanging( wxNotebookEvent& event )
{
//use the stored value of ht here
}
under Windows, GetSelection() will return the same value as
GetOldSelection() when called from the EVT_BOOKCTRL_PAGE_CHANGING
handler and not the page which is going to be selected.
So, call GetSelection from EVT_BOOKCTRL_PAGE_CHANGED to get the new page.
No, there is no workaround (if there were a reliable way to do it, wxWidgets would have been already doing it), the underlying native control simply doesn't provide this information.
You can either ask whatever you need to ask the user about in any case, independently of the page they're switching to, or ask them after they will have already switched -- which is, of course, going to look weird if you then decide to switch back.
If you really, really need this functionality, you might use non-native wxAuiNotebook instead.
CalendarViewDayItemChanging seems to be the way to add 'density colors' (coloured bars in a DayItem box) to a Windows Universal App CalendarView.
However CalendarViewDayItemChanging is only fired when the DayItem box is loaded i.e. on initial loading and possibly when navigating to a far enough date and back again such that the virtualisation re-loads the DayItem.
However when I create an appointment on the selected date I need to add a density color bar immediately, similarly if I remove an appointment, I need to remove that bar.
How do I get the control to reload or re-render that particular DayItem?
Notes:
There is only the SelectedDates available as a property
There is no obvious way to ge the DayItem collection
Setting the Visibility to Collapsed then Visible instantaneously does not trigger a reload.
There was a similar issue on the MSDN blogs here: https://social.msdn.microsoft.com/Forums/en-US/54c81ada-4147-474b-8425-524ec69bc749/uwp-calendarview?forum=wpdevelop
I think your best bet currently is to have your Appointment creation on a separate page and store a List of Appointments locally or in a db. That way when you navigate back to the Page with your calendar view you can reload the Calendar using the updated Appointment list.
I used the MyCalendarView.UpdateLayout method to force the control to hit the CalendarViewDayItemChanging event again.
I called the method from the DataContextChanged event on my UserControl. This way anytime I change the DataContext the density colors get updated. This is sufficient for my needs. It sounds like you want to do it on a different event.
private void UserControl_DataContextChanged(Windows.UI.Xaml.FrameworkElement sender, Windows.UI.Xaml.DataContextChangedEventArgs args)
{
if (this.DataContext is ObservableCollection<Event>)
{
eventCalendar.UpdateLayout();
}
}
In a Silverlight 4.0 (with Prism) application I am maintaining, a page has a Search button which makes WCF service call asynchronously to fetch some data from database, based on the search criteria entered by the user. During the search operation (i.e. from the time Search button is clicked till the time search results are displayed on page), a progress bar window (Silverlight child window) is shown on top of the page (I know it blocks the user for the duration, but this is how all the pages of the application were designed and I cannot change it). Sometimes the Search operation takes long time (several minutes) to return and show the data, and sometimes it shows the results really fast, depending on the search criteria. Now the users want the flexibility to be able to cancel any Search operation if they feel it is taking too much time to show the results.
To address this requirement, I tried the following:
1) Added a Cancel Search button on the Progress-bar window.
2) Added a public static boolean variable (Cancel Search flag, with default value false) in the Progress bar's ViewModel.
3) In the Cancel Search button's click command handler in the same viewmodel, set the Cancel Search flag to true and then closed the Progress bar window.
4) In the asynchronous WCF Serach Service's callback method, first checked if the Progress bar's Cancel Search flag is true. If yes, ignore the results (don't do anything). Otherwise, bound the returned result to the UI as usual.
However, when testing the Cancel Search button, I found that the WCF callback method is getting called before the Cancel button's click command handler, hence the search results are getting displayed even when Cancel Search button is clicked. Obviously this will happen for short running WCF calls which gets executed and completed before the user can click the Cancel button. For long running WCF calls (which gets several minutes to get the results), the above solution may work fine. But while hitting the search button, I do not have any way to know if it is going to be a short-running async call or long running, do I? So is it at all possible to fulfill the requirement in this way or using some other way? Making synchronous WCF call perhaps (but again I gathered it's a big no-no for Silverlight?
When you subscribe to any asynchronous operation from the WCF the WCf sends back the response to the handler with the results.
In your case you have a search button which talks to WCF for result but in case where the wait time is more you want a mechanism to break the operation.
When you click on the cancel button you try to unsubscribe from the event so that you instruct not to listen the callback resulting no results. This can be achieve by using -= operator with yout callback handler.
Hope this helps.
Add a CanExecuteCancelCommand for the Cancel command that checks a boolean variable. When you initiate the call to the WCF service, set this variable to true and call the RaiseCanExecuteChanged method of the command. Equally, as soon as the WCF service returns, set the property to false and call the RaiseCanExecuteChanged method again.
This allows the user to click the button only while you are waiting for the service to return its result.
Something like this:
private bool _canCancelWCFService = false;
DelegateCommand _WCFCommand;
void Method()
{
_WCFCommand = new DelegateCommand(ExecuteWCFService, CanExecuteWCFService);
}
private bool CanExecuteWCFService()
{
return _canCancelWCFService;
}
private void ExecuteWCFService()
{
_canCancelWCFService = true;
_WCFCommand.RaiseCanExecuteChanged();
_wcfService.Completed += new EventHandler<CompletedEventArgs>(CompletedCallback);
//make WCF call here
_wcfService.DoSomething();
}
static void CompletedCallback(object sender, CompletedEventArgs e)
{
_canCancelWCFServiceCall = false;
_WCFCommand.RaiseCanExecuteChanged();
//Process results here...
}
I attach three events to my CustomLists:
ItemAdded
ItemUpdated
ItemDeleting
On one list I have a workflow, which is changing columns in that list. So when I edit an entry in that list, the ItemUpdated-Event fires two times. On the other lists (without any workflows) my receiver is working fine.
How can I find out if a workflow called my event receiver?
Is there a difference between a workflow which fires the event, or a user who fires the event?
You can add hidden field to the list which is always sets by workflow (and only by workflow). Then you will see if workflow called the event receiver.
Or
You can create HandleEventFiring class in your workflow project and use DisableAllEventFiring and EnableAllEventFiring before and after updates in workflow
public class HandleEventFiring : SPItemEventReceiver
{
public void DisableAllEventFiring()
{
this.DisableEventFiring();
}
public void EnableAllEventFiring()
{
this.EnableEventFiring();
}
}
To answer your first question:
Yes, you can find your workflow. The easiest way would be to use the SharePointManager 2010 and
Navigate to your site collection is located
Lists -> [Your List] -> Event Receivers
Check each Event Receiver's properties and delete the event receiver that is firing twice.
I don't know if I understand your second question correctly, but here goes:
A workflow can be started manually by a user or automatically if a List Item is
Added
Updated or
Deleted
Other than that there is not much of a differance.
I have created a search page in a Windows 8 Style App. I have implemented ISupportIncrementalLoading and when the user scrolls the paging works great.
The problem that I'm having is when a user does a second search. I apparently don't know how to get the LoadMoreItemsAsync to fire again. I've tried the following:
1) Clear the underlying collection that is Observable and supports ISupportIncrementalLoading. This clears all items from screen so I know it is bound properly.
2) Replace the underlying collection instance entirely that implements ISupportIncrementalLoading and raise INotifyPropertyChanged so the view knows the property was changed. This also, clears all the items from the screen.
However, the LoadMoreItemsAsync doesn't want to fire after clearing or replacing the underlying collection instance. My hunch is that the UI doesn't think it needs to Load any more, but since I've clear all the items it should want to load more.
I have verified that the HasMoreItems property is set to true.
If it would help, regrettably, you can see the error in production if you download FlixPicks from the Windows 8 store. The steps to reproduce are:
Search using windows search contract
Notice paging works From the Search page
Search again.
Notice all items are cleared. (At this point the LoadMoreItemsAsync is not firing)
Thanks for any advice you can provide!
This definitely looks like a bug. To solve this, add the following line after resetting your collection (in any of the cases):
gv.LoadMoreItemsAsync();
You can probably inherit from the control and create some overrides that will do this automatically:
I know this is an older issue, but I also encountered it and thought others may benefit from an MVVM approach to resolving it. My fix was, after resetting the collection, load a single item into the collection.
private async Task ResetCollectionAsync()
{
Clear();
await LoadMoreItemsAsync(1);
}
The collection is emptied and a single item is re-added. The GridView/ListView control detects the CollectionChanged event and re-queries HasMoreItems to determine whether to load additional data.
This behaviour is baked into IncrementalLoadingCollection (v1.0.1), which also supports filtering and sorting functionality out of the box.
I'm reviving an old question, but I found a solution when none of the previous answers worked for me.
myCollection = new MyIncrementalLoadingCollection();
myListView.ItemSource = myCollection; //This is what I was missing!
Since I wanted the list view to refresh every time the page was navigated to, this was my end result.
protected override async void OnNavigatedTo(NavigationEventArgs e) {
_logItems = new CommandLogIncrementalLoadingCollection();
logListBox.ItemsSource = _logItems;
}