Weird SharePoint ItemUpdating Behavior - c#

I have a SharePoint list where I register a custom ItemUpdating event receiver but I am seeing some really strange behavior in this solution. This behavior occurs if I add any code to the event receiver other than base.ItemUpdating.
What happens is if I debug the event receiver I can see that properties.AfterProperties has all the values entered on the field and properties.ListItem has the original item. But once the ER finishes running and the page reloads nothing is saved and it just returns to what it was before I changed values. Even more weird, if I go and manually set the after properties similar to below it works and the updates are saved correctly. So basically the event receiver is making me responsible to do any changes to the item but this is not normal behavior for ItemUpdating. Does anyone have any idea what might cause this?
public override void ItemUpdating(SPItemEventProperties properties)
{
var recurringBefore = properties.ListItem.TryGetValue<bool>(Constants.CommonFields.Recurring_STATIC);
var recurringAfter = Convert.ToBoolean(properties.AfterProperties[Constants.CommonFields.Recurring_STATIC]);
//This loop is the horrible fix I have done to manually update the relevant fields but this shouldn't be necessary
var item = properties.ListItem;
foreach (SPField key in item.Fields)
{
if (item[key.InternalName] != properties.AfterProperties[key.InternalName] && key.CanBeDisplayedInEditForm && properties.AfterProperties[key.InternalName] != null)
{
//looping through and setting the AfterProperties to what they already are makes them save? If I don't do this nothing saves
properties.AfterProperties[key.InternalName] = properties.AfterProperties[key.InternalName].ToString();
}
}
if (!recurringBefore && recurringAfter &&
currWfStatus == Constants.WorkflowStatus.Processed)
{
//do some stuff
}
base.ItemUpdating(properties);
}

Is it because you are not saving current item at all, something like this:
item.update();

Related

Int field in Winform does not update null values in SQL Server database using C#

In my Winforms C# application, I have fields with Int data type and they are set to accept null values in SQL Server database (allow nulls).
In the forms I have some textboxes which are bound to those int data type fields. If I don't enter anything while creating a new record, it accepts. If I enter a number in the textbox, it also accepts it, and then if I delete it, it doesn’t accept it anymore and even doesn't allow me to move to the next field.
If I set its value as null or "" through code, it simply ignores and does not even update changes which I made in other non int text fields.
I am using following method to update.
this.Validate();
this.itemsbindingSource.EndEdit();
this.tableAdapterManager.UpdateAll(this.sBSDBDataSet);
What can I do for the textbox to accept null values?
I have tried following.
IDTextBox.Text = "";
IDTextBox.Text = null;
I have tried following with the help of above solutions (specially Mr. Ivan) and this is how it worked out.
To clear the int field on the form:
IDTextBox.Text = String.Empty;
Then on Designer.cs file of the form, as suggested by Mr. Ivan, I searched for 'IDtextbox.DataBindings.Add' and replaced
this.IDTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.itemsbindingSource, "PictureID", true));
with
this.IDTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.itemsbindingSource, "PictureID", true, System.Windows.Forms.DataSourceUpdateMode.OnValidation, ""));
It took me a whole day to search and finally I posted my problem here, and it got solved in 1 hour.
This seems to be one of the WF data binding bugs. I can't say what exactly is causing it, but in order to make it work one should set Binding.NullValue property to "" (empty string, the default is null).
I couldn't find a way to do that in the designer, and also it would be quite annoying to locate all text boxes needed. So I would suggest you the following quick-and-dirty approach. Create a helper method like this:
public static class ControlExtensions
{
public static void FixTextBoxBindings(this Control control)
{
if (control is TextBox)
{
foreach (Binding binding in control.DataBindings)
if (binding.NullValue == null) binding.NullValue = "";
}
foreach (Control child in control.Controls)
child.FixTextBoxBindings();
}
}
and then simply include the following in your form Load event:
this.FixTextBoxBindings();
TextBox dont accept null value.
You can check if it null and set String.Empty;
If(dbValue == null)
{
IDTextBox.Text = String.Empty;
}
else
{
// here set value to your textbox
}

MVVM multiple selection, keep after data reloading

I'm using listview that must be able to cope with multiselection. To achieve it I use solution described at MultiSelection not working in ListView (Ankesh answer). It works fine. In my application some timer is working which retrieves devices status every 10 seconds and it assign ObservableCollection as ItemsSource to my ListView and then my selected rows are deselected.
I thought that when I store selected items before reloading data to temporary variable and assign it later it will work, but I have some problems which I can't diagnose.
This is my code (reloading data block):
if (SelectedMachines != null)
{
foreach (var selectedMachine in SelectedMachines)
{
oldSelected.Add(selectedMachine.Clone()); // clone objects
}
SelectedMachines.Clear();
}
Machines = Controller.GetAutomats(); // assign data
if (SelectedMachines != null) // restore selection
{
foreach (var selectedMachine in oldSelected)
{
SelectedMachines.Add(Machines.Where(t => t.Id == selectedMachine.Id).FirstOrDefault());
// at this point SelectedMachines has same elements count as before assign
}
}
Unfortunately such code clears selection after reloading data.

Why is my PropertyChanged event firing twice?

I'm using wpf, mvvmlight and EF. I have two properties on my entity object which are loosely linked and in my XAML, I would like to have one change when the other changes. Right now, I'm having a problem with the first property changed event firing twice.
My xaml setup is like this, I have DataGrid up top on my xaml, I have my
ItemsSource="{Binding MonthlyDonorDetails}" IsSynchronizedWithCurrentItem="True"
The textbox is like,
<TextBox Grid.Column="0" Text="{Binding BankCustomerID}"/>
Next, in my VM, I load up the data like this,
int rowID = 1;
foreach(var row in monthlyDonorsQuery)
{
row.RowID = rowID++;
row.PropertyChanged += new PropertyChangedEventHandler(MonthlyDonorDataRow_PropertyChanged);
}
MonthlyDonorDetails = new ObservableCollection<MonthlyDonorFundCode>(monthlyDonorsQuery);
This affords me a row id on each row to help user differentiate, and (I'm thinking) allows me to setup a handler for when individual fields change within the row. Then I set the backing collection for the grid. And this is all working just fine.
NOW, I want to be able to keep two fields in lock-step with each other, an AccountID and an CustomerID. When the user manually\typing\input changes the AccountID fields, I want to have some code to change the CustomerID, but I don't want this firing needlessly multiple times. Right now its firing twice, and I don't know why? Can anyone see my mistake please?
private void MonthlyDonorDataRow_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if(e.PropertyName == "FirstName" || e.PropertyName == "LastName")
RaisePropertyChanged("DonorName");
if(e.PropertyName == "AccountID")
{
MonthlyDonorFundCode monthlyDonation = sender as MonthlyDonorFundCode;
int customerID = GetCimsIdFromBankCustomerID(monthlyDonation.AccountID);
Debug.WriteLine("should be setting to " + customerID);
}
}
When I'm debugging this, all I can see is the EF setter is getting called twice, but I don't know why cause I'm not setting that value. Any help\guidance would be appreciated. Thank you very much.
I think I found out my problem. But it raises another problem for me. I'm calling the method which adds a PropertyChanged handler, twice, while loading. That's another problem I have to figure out.
Thank you Lavr for trying to help me out.
Put breakpoint in AccountID setter and look at stack trace then setter is called. You can find "who" updating your property twice.
Also you can update AccountID setter like this:
private int _accountId;
public int AccountID
{
get { return this._accountId; }
set
{
if (this._accountId == value) return;
this._accountId = value;
this.RisePropertyChanged("AccountID");
}
}
I have the same problem with twice invocation of propertychanged. The same thing when I try to catch the extra invoke of the propertychanged, the call stack says it is called from the [External Code]. After I upgraded my Xamarin version from 4.0 to latest (Xamarin 5.0).

Item Adding in event receiver sharepoint 2010

public override void ItemAdding(SPItemEventProperties properties)
{
base.ItemAdding(properties);
SPItem itemBeingAdded = properties.ListItem;
var startTime = itemBeingAdded["Start Time"];
// Some code goes here.
}
I am firing this event while adding an item in a calender list. It is getting fired. No problem. But I am not getting any value from properties. In the above code startTime gives me nothing. Actually, I want to access the column field of the item (properties in my case) is being added.
When the user will click in save button, How can I get the column value in code behind (Inside the ItemAdding(SPItemEventProperties properties) method). Let say, I need Start Time and End Time to compare them with some other values. Problem is in the ItemAdding method. ItemUpdating is working fine.
public override void ItemUpdating(SPItemEventProperties properties)
{
base.ItemUpdating(properties);
SPItem itemBeingAdded = properties.ListItem;
var startTime = itemBeingAdded["Start Time"];
}
Finally, I got my answer from here. The way would be like following
string message = properties.AfterProperties["Description"].ToString();
Another thing is you should use internal name. For my case, display name didn't work.

Does the ASP.NET ParameterCollection (or its ParametersChanged event) depend on viewstate?

Using reflector I found the following code in the System.Web.UI.WebControls.Parameter class:
internal void UpdateValue(HttpContext context, Control control)
{
object obj2 = this.ViewState["ParameterValue"];
object obj3 = this.Evaluate(context, control);
this.ViewState["ParameterValue"] = obj3;
if (((obj3 == null) && (obj2 != null)) ||
((obj3 != null) && !obj3.Equals(obj2)))
{
this.OnParameterChanged();
}
}
The line
this.OnParameterChanged();
is what triggers the ParametersChanged-event in the end, as I understand (through this._owner.CallOnParametersChanged() in OnParameterChanged).
Now my question is: what happens if EnableViewState is set to false (e.g. on the whole page)? And as an addendum: I am using ControlParameters pointing at the SelectedValue of a DropDownList.
I assume this would mean:
obj2 would either be the value that has been set earlier in the same request (i.e. UpdateValue has been called before) or null if no other value has been set yet.
As a DropDownLists SelectedValue cannot be null obj3 will never be null.
OnParametersChanged will always be invoked the first time UpdateValues is called in any request.
But if the same entries are loaded into the DropDownList during a PostBack ASP.NET retains the selection in the list across the PostBack even if ViewState is disabled (I can only guess how that works but it does...).
This comes down to the following: if ViewState is disabled and the same values are being loaded into the DropDownList on every request and the user had chosen entry X "long ago" and triggered a PostBack by other means than changing the selection in the DropDownList ASP.NET would fire a ParametersChanged-event on the ParameterCollecion (because of #3 in the list above) although in my understanding the parameter did not change its value.
Am I wrong or does this mean I cannot (should not) disable ViewState if this behaviour is causing trouble?
UPDATE (not directly related to the question)
Just to get rid of the question how the DropDownList preserves the selected value through a post back if viewstate is disabled: by its implementation of IPostBackDataHandler...
Reflector reveals (in DropDownList):
protected virtual bool LoadPostData(string postDataKey,
NameValueCollection postCollection)
{
string[] values = postCollection.GetValues(postDataKey);
this.EnsureDataBound();
if (values != null)
{
base.ValidateEvent(postDataKey, values[0]);
int selectedIndex = this.Items.FindByValueInternal(values[0], false);
if (this.SelectedIndex != selectedIndex)
{
base.SetPostDataSelection(selectedIndex);
return true;
}
}
return false;
}
So it essentially retrieves the value of the selected item in the POSTed data and if it can find an item with this key in the list of items the DropDownList contains it sets it as selected.
You are correct: you cannot disable viewstate if you want the ASP.NET web control 'changed' events and behaviors to work.
The basic mechanism they use to determine whether there has been a change is to compare the value serialized in viewstate to the equivalent posted value (if any). TextBox.TextChanged (for example) spells this out clearly in its class documentation:
A TextBox control must persist some
values between posts to the server for
this event to work correctly. Be sure
that view state is enabled for this
control.

Categories

Resources