Skip to main content

Microsoft Silverlight

Answered Question Dataforms, Commit, Cancel and ComboboxesRSS Feed

(0)

aikar
aikar

Member

Member

1 points

11 Posts

Dataforms, Commit, Cancel and Comboboxes

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.AdressTypenIdea.Id == adresse.AdressTypId)
40   				{
41   					this.AdressTyp = Session.Instance.AdressTypenIdea;
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
Ardman

Contributor

Contributor

3344 points

926 Posts

Re: Dataforms, Commit, Cancel and Comboboxes

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.

aikar
aikar

Member

Member

1 points

11 Posts

Re: Dataforms, Commit, Cancel and Comboboxes

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.

 

 

Ardman
Ardman

Contributor

Contributor

3344 points

926 Posts

Re: Re: Dataforms, Commit, Cancel and Comboboxes

Do you have an include attribute in your metadata?

aikar
aikar

Member

Member

1 points

11 Posts

Re: Re: Dataforms, Commit, Cancel and Comboboxes

 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?

Ardman
Ardman

Contributor

Contributor

3344 points

926 Posts

Re: Re: Re: Dataforms, Commit, Cancel and Comboboxes

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.

aikar
aikar

Member

Member

1 points

11 Posts

Re: Re: Re: Dataforms, Commit, Cancel and Comboboxes

 I'm not sure if I am understanding what you mean. Would you give me a short example or a link to an example?

Ardman
Ardman

Contributor

Contributor

3344 points

926 Posts

Re: Re: Re: Re: Dataforms, Commit, Cancel and Comboboxes

Here is my NoteMetadata:

internal sealed class NoteMetadata

{

/// <summary>

/// NoteId field

/// </summary>

[ReadOnly(true)]

[Key]

public int NoteId;

/// <summary>

/// RecordId field

/// </summary>

public int RecordId;

/// <summary>

/// TableId field

/// </summary>

public int TableId;

/// <summary>

/// Prevents a default instance of the NoteMetadata class from being created.

/// </summary>

private NoteMetadata()

{

}

/// <summary>

/// Gets or sets the DateCreated

/// </summary>

public DateTime DateCreated { get; set; }

/// <summary>

/// Gets or sets the Description

/// </summary>

public string Description { get; set; }

/// <summary>

/// Gets or sets the EntityState

/// </summary>

public EntityState EntityState { get; set; }

/// <summary>

/// Gets or sets a value indicating whether IsActive

/// </summary>

public bool IsActive { get; set; }

/// <summary>

/// Gets or sets the Users

/// </summary>

[Include] // <-- I want to Include the User table data

public User Users { get; set; }

}

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:

public IQueryable<Note> GetNotes()

{

return this.Context.Notes.Include("Users").Where(n => n.IsActive == true).OrderByDescending(n => n.DateCreated);

}

This makes sure that the data is brought back within the query.

aikar
aikar

Member

Member

1 points

11 Posts

Re: Re: Re: Re: Dataforms, Commit, Cancel and Comboboxes

 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?

Ardman
Ardman

Contributor

Contributor

3344 points

926 Posts

Re: Re: Re: Re: Re: Dataforms, Commit, Cancel and Comboboxes

Are you using RIA services?

aikar
aikar

Member

Member

1 points

11 Posts

Re: Re: Re: Re: Re: Dataforms, Commit, Cancel and Comboboxes

  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  
 

 

Ardman
Ardman

Contributor

Contributor

3344 points

926 Posts

Re: Re: Re: Re: Re: Re: Dataforms, Commit, Cancel and Comboboxes

Try changing your AutoCommit from False to True.

aikar
aikar

Member

Member

1 points

11 Posts

Re: Re: Re: Re: Re: Re: Dataforms, Commit, Cancel and Comboboxes

 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 Tang - MSFT
Min-Hong...

Contributor

Contributor

3375 points

377 Posts

Answered Question

Re: Re: Re: Re: Re: Re: Dataforms, Commit, Cancel and Comboboxes

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

Min-Hong Tang
Microsoft Online Community Support

Please remember to mark the replies as answers if they help and unmark them if they provide no help.

aikar
aikar

Member

Member

1 points

11 Posts

Re: Re: Re: Re: Re: Re: Dataforms, Commit, Cancel and Comboboxes

 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

  • Unanswered Question
  • Answered Question
  • Announcement
Microsoft Communities