Skip to main content
Home Forums General Silverlight New Features in Silverlight 3 Dataforms, Commit, Cancel and Comboboxes
14 replies. Latest Post by aikar on November 4, 2009.
(0)
aikar
Member
1 points
11 Posts
10-30-2009 5:46 AM |
Hello everyone
I'm working with Silverlight for about two weeks now, so I'm rather new.
Im trying to work with DataForms at the moment and have some problems:
The commit-function is only called when changes have been done and the Commit button is pressed, else the Cancel-function is called. But in both cases it seems to take the changes directly to the binded object, there is no automatic reset, so what is the difference in the Cancel-Case? Only the different function-call? Do I have to reset the values myself?
Another problem are combo boxes. I have managed to set the initial selected value by binding, but the (TwoWay-)binding seems not to work, changes of the combo-box do not effect the object and if I only change the combo box but no text box, the Commit button triggers the Cancel-function instead of the Commit-function.
Here is my EditableObject, as you can see, I have implemented a data reset by myself when the Cancel-Function is called but it seems a bit of a hack for me, is there a better solution?
1 using System; 2 using System.Net; 3 using System.Windows; 4 using System.Windows.Controls; 5 using System.Windows.Documents; 6 using System.Windows.Ink; 7 using System.Windows.Input; 8 using System.Windows.Media; 9 using System.Windows.Media.Animation; 10 using System.Windows.Shapes; 11 using System.ComponentModel; 12 using CrmWcfService; 13 using System.Windows.Data; 14 using System.ComponentModel.DataAnnotations; 15 using System.Collections.ObjectModel; 16 17 namespace CrmSilverlightClient.DataObjects 18 { 19 public class AdresseDataObject:IEditableObject 20 { 21 [Required(ErrorMessage = "Straße muss gesetzt sein")] 22 public string Strasse{get;set;} 23 public string Strasse2 { get; set; } 24 [Required(ErrorMessage="Der Adresstyp muss gesetzt sein")] 25 public DtoAdressTyp AdressTyp {get;set;} 26 27 private string StrasseStore{get;set;} 28 private string Strasse2Store { get; set; } 29 private DtoAdressTyp AdressTypStore { get; set; } 30 31 public AdresseDataObject(DtoAdresse adresse) 32 { 33 34 this.Strasse = adresse.Strasse; 35 this.Strasse2 = adresse.Strasse2; 36 37 for(int i=0;i<Session.Insance.AdressTypen.Count;i++) { 39 if(Session.Instance.AdressTypen.Id == adresse.AdressTypId) 40 { 41 this.AdressTyp = Session.Instance.AdressTypen; 42 i = Session.Instance.AdressTypen.Count; 43 44 } 45 } 46 47 if(this.AdressTyp == null) 48 { 49 this.AdressTyp = Session.Instance.AdressTypen[0]; 50 } 51 52 this.StrasseStore = this.Strasse; 53 this.Strasse2Store = this.Strasse2; 54 this.AdressTypStore = this.AdressTyp; 55 } 56 57 public string Header 58 { 59 get 60 { 61 string ret = this.Strasse; 62 63 if(!this.Strasse2.Trim().Equals("")) 64 { 65 ret = ret +" "+this.Strasse2; 66 } 67 ret = ret+ " ("+this.AdressTyp.Name+")"; 68 69 return ret; 70 } 71 } 72 73 public void ResetToLastStorrage() 74 { 75 this.Strasse = this.StrasseStore; 76 this.Strasse2 = this.Strasse2Store; 77 this.AdressTyp = this.AdressTypStore; 78 } 79 80 #region IEditableObject Members 81 82 public void BeginEdit() 83 { 84 85 } 86 public void CancelEdit() 87 { 88 this.ResetToLastStorrage(); 89 } 90 91 public void EndEdit() 92 { 93 this.StrasseStore = this.Strasse; 94 this.Strasse2Store = this.Strasse2; 95 this.AdressTypStore = this.AdressTyp; 96 } 97 98 #endregion 99 } 100 101 102 103 } 104
The xaml:
1 <UserControl x:Class="CrmSilverlightClient.AdresseDataFormControl" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:df="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit" 5 xmlns:Local="clr-namespace:CrmSilverlightClient" 6 > 7 <Grid x:Name="LayoutRoot" Background="Transparent" Width="500" Height="400"> 8 <Grid.RowDefinitions> 9 <RowDefinition Height="40"/> 10 <RowDefinition Height="*"/> 11 </Grid.RowDefinitions> 12 <Button x:Name="AdresseCloseButton" Grid.Row="0" HorizontalAlignment="Right" Style="{StaticResource CloseButton}" Click="AdresseCloseButton_Click"/> 13 <df:DataForm x:Name="AdresseDataForm" Grid.Row="1" IsReadOnly="False" AutoCommit="False" AutoEdit="True" AutoGenerateFields="False" CancelButtonContent="Zurücksetzen" CommitButtonContent="Speichern"> 14 <df:DataForm.EditTemplate> 15 <DataTemplate> 16 <Grid> 17 <Grid.RowDefinitions> 18 <RowDefinition Height="40"/> 19 <RowDefinition Height="40"/> 20 <RowDefinition Height="40"/> 21 <RowDefinition Height="40"/> 22 </Grid.RowDefinitions> 23 <df:DataField Label="Straße" Margin="5,5,5,5" Grid.Row="0"> 24 <TextBox Text="{Binding Strasse, Mode=TwoWay}"/> 25 </df:DataField> 26 <df:DataField Label="Straße 2" Margin="5,5,5,5" Grid.Row="1"> 27 <TextBox Text="{Binding Strasse2, Mode=TwoWay}"/> 28 </df:DataField> 29 <df:DataField Label="Adresstyp" Margin="5,5,5,5" Grid.Row="2"> 30 <ComboBox x:Name="AdressTypComboBox" DisplayMemberPath="Name" SelectedItem="{Binding AdressTyp, Mode=TwoWay}"/> 31 </df:DataField> 32 </Grid> 33 </DataTemplate> 34 </df:DataForm.EditTemplate> 35 </df:DataForm> 36 </Grid> 37 </UserControl> 38
And the cs-File for the xaml:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Net; 5 using System.Windows; 6 using System.Windows.Controls; 7 using System.Windows.Documents; 8 using System.Windows.Input; 9 using System.Windows.Media; 10 using System.Windows.Media.Animation; 11 using System.Windows.Shapes; 12 using CrmSilverlightClient.DataObjects; 13 using CrmWcfService; 14 15 namespace CrmSilverlightClient 16 { 17 public partial class AdresseDataFormControl : UserControl 18 { 19 public AdresseDataFormControl() 20 { 21 InitializeComponent(); 22 23 this.AdresseDataForm.ContentLoaded += new EventHandler(this.ContentLoaded); 24 25 } 26 27 private void AdresseCloseButton_Click(object sender, RoutedEventArgs e) 28 { 29 AdresseDataObject dataObject = this.AdresseDataForm.CurrentItem as AdresseDataObject; 30 31 dataObject.ResetToLastStorrage(); 32 33 this.Visibility = Visibility.Collapsed; 34 } 35 36 private void ContentLoaded(object sender, DataFormContentLoadEventArgs e) 37 { 38 ComboBox adressTypen = this.AdresseDataForm.FindNameInContent("AdressTypComboBox") as ComboBox; 39 40 adressTypen.ItemsSource = Session.Instance.AdressTypen; 41 } 42 43 } 44 } 45
Ardman
Contributor
3344 points
926 Posts
10-30-2009 5:57 AM |
For you ComboBox you need to add a SelectionChanged event handler. In this event handler, you could try:
ComboBox cb = sender as ComboBox;
this.name = cb.SelectedItem as AdressTyp;
Add a property called name:
public AdressType name { get; set; }
and this should work.
10-30-2009 6:16 AM |
Thank you for your quick response. Unfortunately it did not work. I have added an event handler:
private void AdressTypComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { ComboBox adressTypen = sender as ComboBox; AdresseDataObject dataObject = this.AdresseDataForm.CurrentItem as AdresseDataObject; dataObject.AdressTyp = adressTypen.SelectedItem as DtoAdressTyp; }
The Method is called but when I click on the Commit-Button after a selection change, it still calls the Cancel-Method.
And another question: Why is an element (Combobox, Textbox,..) within an DataField not directly accessible from the cs-file? I had to use this.AdresseDataForm.FindNameInContent("AdressTypComboBox") instead of this.AdressTypComboBox.
10-30-2009 6:26 AM |
Do you have an include attribute in your metadata?
10-30-2009 6:34 AM |
No. Should I? I have to admit, I had not worked much with metadata and never had worked with the include attribute before, what is it used for?
10-30-2009 6:43 AM |
You need to add the Include attribute. Associations marked with the Include attribute will actually be traversed. This ensures that information you have explicitly decided to expose is exposed.
10-30-2009 6:50 AM |
I'm not sure if I am understanding what you mean. Would you give me a short example or a link to an example?
10-30-2009 6:58 AM |
Here is my NoteMetadata:
internal
{
[
}
So, in order for me to obtain the information from the User table, I have added the Include attribute. I have also used the .Include in my query:
This makes sure that the data is brought back within the query.
10-30-2009 9:24 AM |
So I have to set
[Include] public Category Category {get;set;}
?
Or do you mean something else? What is [Include] going to do? I have googled for C# metadata Include attribute but have not found usable information
Additionaly, [Include] is not found by the compiler. Do I need a special reference?
10-30-2009 9:43 AM |
Are you using RIA services?
11-02-2009 10:00 AM |
No. My Data is basically comming from an WCF-Service but the Silverlight-Control I am talking about is fully working on local IEditableObjects. Maybe it's not clear what I was asking for (I'm from Austria and my English was not trained very well in the last month).However, I have solved some of my problems by myself but one problem with ComboBoxes still occurs: When I am using textboxes for the data fields and I am typing in Edit-Mode, the Commit button is enabled and I am not allowed to switch to another object when I use a Collection as DataSource which is a good feature in my opinion.But when I use a ComboBox or fill the TextBoxes automatically, the Commit-Button is not enabled and the switch-buttons are not disabled, even when the IEditableObject is changed because of the binding (The binding works, I have checked the values of the object).
The DataForm seems not to recognize that a change by a ComboBox is a change which has to be committed.
How can I "tell" the DataForm that it has to enable/disable the buttons as when I type into a TextBox?
My actual DataForm-Xaml:
1 <UserControl x:Class="CrmSilverlightClient.AdresseDataFormControl" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:df="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit" 5 xmlns:Local="clr-namespace:CrmSilverlightClient" 6 > 7 <Grid x:Name="LayoutRoot" Background="Transparent" Width="500" Height="400"> 8 <Grid.RowDefinitions> 9 <RowDefinition Height="40"/> 10 <RowDefinition Height="*"/> 11 </Grid.RowDefinitions> 12 <Button x:Name="AdresseCloseButton" Grid.Row="0" HorizontalAlignment="Right" Style="{StaticResource CloseButton}" Click="AdresseCloseButton_Click"/> 13 <df:DataForm x:Name="AdresseDataForm" Grid.Row="1" IsReadOnly="False" AutoCommit="False" AutoEdit="True" AutoGenerateFields="False" CancelButtonContent="Zurücksetzen" CommitButtonContent="Speichern"> 14 <df:DataForm.EditTemplate> 15 <DataTemplate> 16 <Grid> 17 <Grid.RowDefinitions> 18 <RowDefinition Height="40"/> 19 <RowDefinition Height="40"/> 20 <RowDefinition Height="40"/> 21 <RowDefinition Height="40"/> 22 </Grid.RowDefinitions> 23 <df:DataField x:Name="StrasseDataField" Label="Straße" Margin="5,5,5,5" Grid.Row="0"> 24 <TextBox x:Name="StrasseTextBox" Text="{Binding Strasse, Mode=TwoWay}"/> 25 </df:DataField> 26 <df:DataField Label="Straße 2" Margin="5,5,5,5" Grid.Row="1"> 27 <TextBox Text="{Binding Strasse2, Mode=TwoWay}"/> 28 </df:DataField> 29 <df:DataField Label="Adresstyp" Margin="5,5,5,5" Grid.Row="2"> 30 <ComboBox x:Name="AdressTypComboBox" DisplayMemberPath="Name" SelectedItem="{Binding AdressTyp, Mode=TwoWay}" /> 31 </df:DataField> 32 </Grid> 33 </DataTemplate> 34 </df:DataForm.EditTemplate> 35 </df:DataForm> 36 </Grid> 37 </UserControl> 38
My actual Control:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Net; 5 using System.Windows; 6 using System.Windows.Controls; 7 using System.Windows.Documents; 8 using System.Windows.Input; 9 using System.Windows.Media; 10 using System.Windows.Media.Animation; 11 using System.Windows.Shapes; 12 using CrmSilverlightClient.DataObjects; 13 using CrmWcfService; 14 15 namespace CrmSilverlightClient 16 { 17 public partial class AdresseDataFormControl : UserControl 18 { 19 public AdresseDataFormControl() 20 { 21 InitializeComponent(); 22 23 this.AdresseDataForm.ContentLoaded += new EventHandler(this.ContentLoaded); 24 } 25 26 private void AdresseCloseButton_Click(object sender, RoutedEventArgs e) 27 { 28 AdresseDataObject dataObject = this.AdresseDataForm.CurrentItem as AdresseDataObject; 29 30 if(dataObject!=null) 31 { 32 dataObject.ResetToLastStorrage(); 33 } 34 35 this.Visibility = Visibility.Collapsed; 36 } 37 38 private void ContentLoaded(object sender, DataFormContentLoadEventArgs e) 39 { 40 ComboBox adressTypen = this.AdresseDataForm.FindNameInContent("AdressTypComboBox") as ComboBox; 41 42 adressTypen.ItemsSource = Session.Instance.AdressTypen; 43 } 44 45 } 46 } 47
And my DataObject:
1 using System; 2 using System.Net; 3 using System.Windows; 4 using System.Windows.Controls; 5 using System.Windows.Documents; 6 using System.Windows.Ink; 7 using System.Windows.Input; 8 using System.Windows.Media; 9 using System.Windows.Media.Animation; 10 using System.Windows.Shapes; 11 using System.ComponentModel; 12 using CrmWcfService; 13 using System.Windows.Data; 14 using System.ComponentModel.DataAnnotations; 15 using System.Collections.ObjectModel; 16 17 namespace CrmSilverlightClient.DataObjects 18 { 19 public class AdresseDataObject : DataObject 20 { 21 private string _strasse; 22 23 [Required(ErrorMessage = "Straße muss gesetzt sein")] 24 public string Strasse{ 25 get 26 { 27 return this._strasse; 28 } 29 set{ 30 this._strasse = value; 31 } 32 } 33 public string Strasse2 { get; set; } 34 35 private DtoAdressTyp _adressTyp; 36 37 [Required(ErrorMessage="Der Adresstyp muss gesetzt sein")] 38 public DtoAdressTyp AdressTyp 39 { 40 get 41 { 42 return this._adressTyp; 43 } 44 set 45 { 46 this._adressTyp = value; 47 } 48 } 49 50 private string StrasseStore{get;set;} 51 private string Strasse2Store { get; set; } 52 private DtoAdressTyp AdressTypStore { get; set; } 53 54 public AdresseDataObject(DtoAdresse adresse) 55 { 56 57 this.Strasse = adresse.Strasse; 58 this.Strasse2 = adresse.Strasse2; 59 60 foreach(DtoAdressTyp adressTyp in Session.Instance.AdressTypen) 61 { 62 if(adressTyp.Id == adresse.AdressTypId) 63 { 64 this.AdressTyp = adressTyp; 65 66 } 67 } 68 69 if(this.AdressTyp == null) 70 { 71 this.AdressTyp = Session.Instance.AdressTypen[0]; 72 } 73 74 this.StrasseStore = this.Strasse; 75 this.Strasse2Store = this.Strasse2; 76 this.AdressTypStore = this.AdressTyp; 77 } 78 79 80 public void ResetToLastStorrage() 81 { 82 this.Strasse = this.StrasseStore; 83 this.Strasse2 = this.Strasse2Store; 84 this.AdressTyp = this.AdressTypStore; 85 } 86 87 #region IEditableObject Members 88 89 public override void BeginEdit() 90 { 91 92 } 93 public override void CancelEdit() 94 { 95 this.ResetToLastStorrage(); 96 } 97 98 public override void EndEdit() 99 { 100 this.StrasseStore = this.Strasse; 101 this.Strasse2Store = this.Strasse2; 102 this.AdressTypStore = this.AdressTyp; 103 104 this.OnPropertyChanged("Header"); 105 } 106 107 #endregion 108 } 109 } 110
11-02-2009 10:07 AM |
Try changing your AutoCommit from False to True.
11-03-2009 3:21 AM |
No Difference. The Commit-Button is now totally gone (What I don't want) but the Forward/Back-Buttons are still not deactivated when I change the selected Item of the ComboBox.
Has anyone done a working example for using ComboBoxes in Dataforms?
My code is based on this one: http://leeontech.wordpress.com/2009/07/27/working-with-dataform/
But this does not solve the problems.
Min-Hong...
3375 points
377 Posts
11-03-2009 10:35 PM |
Hi,
I read your post, and based on my knowledge, it is archievable.
I did a test , building a similar situation with what you provided and i implemented your dataobject INotifyPropertyChanged interface. In my test it worked. When i change the selectection of the combo box, the dataform's navigation button is disabled and it requires you to commit or cancel unless you change back to the original value.
So maybe that is what you are looking for. About how to implement INotifyPropertyChanged interface you can check here:
http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx
Best Regards
11-04-2009 3:16 AM |
That's it!
I had implemented INotifyPropertyChanged in the DataObject-Parent-Class, but I did not throw an explizit event when changing the ComboBox. Now I throw the event when AdressTypComboBox_SelectionChanged is triggered and it works!
Thank you very much