I know, there are a lot of examples but I'm not getting it to work.
I have a Silverlight Mask where I dynamically add UIElements like Textboxes or ComboBoxes. So far, this is working fine. Now I'm trying to set the ComboBox Selected Item from my database values.
I store the information for generation in my own classes.
public class Metadata
{
public int? MetadataId { get; set; }
public string Name { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public int Column { get; set; }
public MetaDataType MetaDataType { get; set; }
public List<MetadataData> MetadataData { get; set; }
}
public class MetadataData
{
public int MetadataDataId { get; set; }
public int MetadataId { get; set; }
public string Description { get; set; }
}
public partial class MetadataStore
{
public Guid MetadataStoreId { get; set; }
public Guid ObjectId { get; set; }
public Guid ModuleTypeId { get; set; }
public int MetadataSetId { get; set; }
public int? MetadataSetSetId { get; set; }
public int MetadataId { get; set; }
public string Description { get; set; }
public int? RowId { get; set; }
public DataContainer.Profile userProfile { get; set; }
}
My selected value stores the MetadataDataId as a String in my MetadataStore in the field Description. I'm generating the UIElements based on the MetaData class in code-behind like this
switch ((MetaDataDataType)metadata.MetaDataType.MetaDataTypeId)
{
case MetaDataDataType.String:
frmElement = new TextBox() { Name = String.Format("dynCtrl_{0}_{1}", metadata.MetadataId, metadata.Name)
AcceptsReturn = false, Margin = new Thickness(4),
HorizontalAlignment = HorizontalAlignment.Left,
Height = metadata.Height, Width = metadata.Width,
Style = App.Current.Resources["TextBoxStyleFlat"] as Style };
frmElement.SetBinding(TextBox.TextProperty,
new Binding { Mode = BindingMode.TwoWay, Path = new PropertyPath(metadata.Name) });
break;
case MetaDataDataType.SingleSelection:
frmElement = new ComboBox()
{
Name = String.Format("dynCtrl_{0}_{1}", metadata.MetadataId, metadata.Name),
Margin = new Thickness(4),
HorizontalAlignment = HorizontalAlignment.Left,
Style = App.Current.Resources["ComboBoxStyleFlat"] as Style,
ItemsSource = metadata.MetadataData,
DisplayMemberPath = "Description",
//SelectedItem = metadata.Name,
Height = metadata.Height,
Width = metadata.Width
};
frmElement.SetBinding(ComboBox.SelectedValueProperty, new Binding { Mode = BindingMode.TwoWay, Path = new PropertyPath(metadata.Name) });
frmElement.SetBinding(ComboBox.SelectedValuePathProperty, new Binding { Mode = BindingMode.TwoWay, Path = new PropertyPath("MetadataDataId") });
default:
break;
}
I thought I could make it work with an Dictionary<string, object>
var p = new Dictionary<string, object>();
p[mData.Metadata.Name] = Convert.ToInt32(item.Description);
but as it didn't work, I ended up with generating a DataTable and selecting the first element which gets me an Object with my desired dynamic properties.
TempObject.Testprop
TempObject.Nutzen
The DataSourceCreator is used from http://blog.bodurov.com/How-to-Bind-Silverlight-DataGrid-From-IEnumerable-of-IDictionary/.
internal static void generateDataContext(List<MetadataSetMetadata> metadataSetMetadata, List<MetadataStore> metadataStore, ref Grid viewGrid)
{
if (metadataStore != null && metadataStore.Count > 0)
{
dynamic expObj = new ExpandoObject();
var p = new Dictionary<string, object>();
foreach (var item in metadataStore.Where(x => x.MetadataSetSetId == null))
{
var mData = metadataSetMetadata.FirstOrDefault(x => x.Metadata != null && x.Metadata.MetadataId.Equals(item.MetadataId));
switch ((MetaDataDataType)mData.Metadata.MetaDataType.MetaDataTypeId)
{
case MetaDataDataType.String:
case MetaDataDataType.LongString:
p[mData.Metadata.Name] = item.Description;
break;
case MetaDataDataType.SingleSelection:
if (!String.IsNullOrWhiteSpace(item.Description))
{
p[mData.Metadata.Name] = Convert.ToInt32(item.Description);
}
break;
default:
break;
}
}
var emtyRowList = new List<IDictionary>();
emtyRowList.Add(p);
viewGrid.DataContext = DataSourceCreator.ToDataSource(emtyRowList).Cast<object>().FirstOrDefault();
viewGrid.UpdateLayout();
}
}
I set the DataContext for the complete StackPanel. My TextBox shows the correct Text stored in TempObject.Testprop. My ComboBox` only displays its Items Source but its not showing my already selected item, which Id is stored in TempObject.Nutzen.
Any ideas what I'm missing?
UPDATE:
I could make it working, binding the SelectedValue to the MetadataData Object instead of its ID value and setting the SelectedValuePath to the ID property name of MetadataData.
I could make it working, binding the SelectedValue to the MetadataData Object instead of its ID value and setting the SelectedValuePath to the ID property name of MetadataData.
Related
I create the small winform to do test bing
Existing class as below
public class Book
{
public int Id { get; set; }
public string BookName { get; set; }
public int? CatalogID { get; set; }
}
public class BookCatalog
{
public int Id { get; set; }
public string CataLogName { get; set; }
}
and I create the form with two control, Textbox and Combobox
which initial as below
private Book BookRecord;
private List<BookCatalog> bookCatalogs;
private BindingSource BindingSource = new BindingSource();
public frmBook()
{
InitializeComponent();
// I have initial one bookrecord and multi bookCatalogs here
cbBookCatagories.DisplayMember = "CataLogName";
cbBookCatagories.ValueMember = "Id";
cbBookCatagories.DataSource = bookCatalogs;
BindingSource.DataSource = BookRecord;
txtBoxBookName.DataBindings.Add("Text", BindingSource, "BookName");
cbBookCatagories.DataBindings.Add("SelectedValue", BindingSource, "CatalogID");
}
The first run is fine, but when I want to clear BookRecord as below code
BookRecord.Id = 0;
BookRecord.BookName = null;
BookRecord.AuthorName = null;
BookRecord.CatalogID = null;
BindingSource.ResetBindings(false);
My combobox cannot change value and always point to zeroindex
can anyone guide me how to handle BindingSource() on comboxbox ?
Thank you
When im displaying my database table it contains a few collections and those dont display in the datagrid. a column is generated but it stays blank. I do not know where to implement this either.
Maybe this will help also to explain what i want to display in the column instead of the ICollection
static void Main(string[] args)
{
using (var db = new Whataboutthisfish())
{
Vis vis = db.Vissen.Find(2);
if(vis != null)
{
if(vis.Continenten != null)
{
string s = "";
if(vis.Continenten.Count() > 1)
{
var continentenLijst = vis.Continenten;
s = continentenLijst.First().Naam;
foreach (Continent c in vis.Continenten)
{
s += ", "+c.Naam;
}
}
else
{
s = vis.Continenten.First().Naam;
}
Console.WriteLine(s);
}
}
}
}
I would like to return 1 string containing each continent's name using a seperator.
Like: "North-America" if there's only 1 continent in the collection
Or: "North-America, South-America" and so on for multiple.
Classes;
[Table("Continenten")]
public partial class Continent
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Continent()
{
Vissen = new HashSet<Vis>();
}
public int Id { get; set; }
[Required]
[StringLength(50)]
public string Naam { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Vis> Vissen { get; set; }
}
}
[Table("Vissen")]
public partial class Vis
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Vis()
{
Continenten = new HashSet<Continent>();
Verbanden = new HashSet<Verband>();
Waterlagen = new HashSet<Waterlaag>();
}
public int Id { get; set; }
[StringLength(200)]
public string Naam { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Continent> Continenten { get; set; }
}
The Xaml for grid:
<DataGrid x:Name="dataGrid" HorizontalAlignment="Left" VerticalAlignment="Top" RenderTransformOrigin="0.833,0.846" Margin="10,10,10,10"/>
In code behind:
using (var db = new Catattafish.Whataboutthisfish())
{
dataGrid.ItemsSource = db.Vissen.ToList();
}
So I have the following setup:
PLANNING:
public class Planning : ViewModelBase
{
public Planning()
{
AddNewActivityCommand = new RelayCommand(AddActivity, CanAddActivity);
}
public ObservableCollection<PlanningItem> PlanningItems { get; set; }
public PlanningItem SelectedPlan { get; set; }
#region AddNewActivity
public RelayCommand AddNewActivityCommand { get; private set; }
private bool CanAddActivity()
{
if (!PlanningItems.Any())
{
return true;
}
if (string.IsNullOrEmpty(PlanningItems[PlanningItems.Count - 1].Activities) != true ||
PlanningItems[PlanningItems.Count - 1].DhpRepresentativeSelected != null)
{
return true;
}
return false;
}
private void AddActivity()
{
PlanningItems.Add(new PlanningItem());
AddNewActivityCommand.RaiseCanExecuteChanged();
}
#endregion
}
PLANNING ITEM:
public class PlanningItem : ViewModelBase
{
private string _activity;
public ObservableCollection<OutreachUser> DhpRepresentativeSource
{
get
{
var userSource = new ObservableCollection<OutreachUser>();
using (var context = new Outreach_Entities())
{
var query = from a in context.UserInfoes
join b in context.PersonalInfoes on a.UserIdentity equals b.PersonIdentity
join c in context.PersonalTitles on b.TitleLink equals c.TitleIdentity into cGroup
from c in cGroup.DefaultIfEmpty()
select new OutreachUser
{
PersonLink = a.UserIdentity,
Username = a.Username,
FirstName = b.FirstName,
MiddleInitial = b.MiddleInitial,
LastName = b.LastName
};
foreach (var result in query)
{
userSource.Add(result);
}
return userSource;
}
}
}
public OutreachUser DhpRepresentativeSelected { get; set; }
public DateTime PlanningDate { get; set; }
public TimeSpan PlanningStart { get; set; }
public TimeSpan PlanningEnd { get; set; }
public int PlanningTotalHours { get; set; }
public string Activities
{
get
{
return _activity;
}
set
{
_activity = value;
RaisePropertyChanged(nameof(Activities), "", _activity, true);
}
}
}
I have a ListBox bound to the PlanningItems Observable Collection.
I want to be able to add a new item to the list if the following criteria are met:
The Planning Items Collection is empty.
The last item in the Planning Items Collection has a DhpRepresentativeSelected that is not null.
The last item in the Planning Items Collection has some text in the Activities string.
The first item is easy enough because I call AddNewActivityCommand.RaiseCanExecuteChanged(); after I add a new item from an empty list.
Now I need to call the AddNewActivityCommand.RaiseCanExecuteChanged(); from within the PlanningItem ViewModel, but it does not have access rights to the command.
Clueless pointed me to the answer.
What I did was inside of my Planning ViewModel I created an internal Method that called the AddNewActivityCommand.RaiseCanExecuteChanged() method. I think called that method from within the PlanningItems ViewModel.
I have a winform powerpacks datareapter control having a picture box. This is the code snippet from the classes.
DisplaySystemUsersControl.Designer.cs
this.picBoxUserImage.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.picBoxUserImage.DataBindings.Add(new System.Windows.Forms.Binding("Image", this.UserBindingSource, "User_Image", true));
this.picBoxUserImage.Location = new System.Drawing.Point(3, 3);
this.picBoxUserImage.Name = "picBoxUserImage";
this.picBoxUserImage.Size = new System.Drawing.Size(100, 93);
this.picBoxUserImage.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.picBoxUserImage.TabIndex = 0;
this.picBoxUserImage.TabStop = false;
this.picBoxUserImage.Click += new System.EventHandler(this.picBoxUserImage_Click);
DisplaySystemUsersControl.cs
public DisplaySystemUsersControl()
{
InitializeComponent();
this.dataRepeaterAccounts.DataSource = this.UserBindingSource;
LoadAccountData();
}
private void LoadAccountData()
{
SystemUserBusinessClass oSystemUserBusinessClass = new SystemUserBusinessClass();
List<SystemUserEntity_Only_For_UI_Binding> obj = oSystemUserBusinessClass.GetSystemUsersForUI();
BindingSource tempUserBindingSource = (BindingSource)dataRepeaterAccounts.DataSource;
obj.ForEach(oSystemUserEntity_Only_For_UI_Binding => tempUserBindingSource.Add(oSystemUserEntity_Only_For_UI_Binding));
}
SystemUserEntity_Only_For_UI_Binding.cs
public class SystemUserEntity_Only_For_UI_Binding
{
public string User_Id { get; set; }
public string User_Name { get; set; }
public byte[] User_Image { get; set; }
}
User ID and User name is getting loaded. But Image is not getting loaded. SystemUserEntity_Only_For_UI_Binding.User_Image() is holding the image byte array.
Can anybody please tell me what is going wrong?
Your class should look something like this:
public class SystemUserEntity_Only_For_UI_Binding
{
public string User_Id { get; set; }
public string User_Name { get; set; }
public Image User_Image { get; set; }
}
The byte array needs to be translated into an image somewhere in your code:
using (MemoryStream ms = new MemoryStream(imgBytes)) {
this.User_Image = Image.FromStream(ms);
}
public void BindRepeater (DataSet dsObj)
{
pictureBox1.DataBindings.Clear();
pictureBox1.DataBindings.Add("ImageLocation", dt, "Photo");
dataRepeater1.DataSource = dsObj;
}
i have a lot of some WPF windows. On them i write some code, which binds UI controls and data, something like this:
public class AddressWindow
{
public string AddressID { get; set; }
public string Addr1 { get; set; }
public string Addr2 { get; set; }
public string ZIP { get; set; }
public string City { get; set; }
public string Mobile { get; set; }
public string FAX { get; set; }
public string Country { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public bool IsSystem { get; set; }
public bool Enabled { get; set; }
}
private void BindInCode()
{
var address = new AddressWindow
{
// AddressID = "110",
// Addr1 = "Kaunas",
// Addr2 = "Jonavos",
// ZIP = "8987",
// City = "miestas",
// Mobile = "869985868",
// FAX = "87998",
// Country = "Lithuania",
// Email = "emailas#ree.lt",
// Phone = "37598288",
// IsSystem = true,
// Enabled = false
};
Binding binding = new Binding();
binding.Source = address;
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
binding.Path = new PropertyPath("AddressID");
this.db_AddressID.SetBinding(TextEdit.TextProperty, binding);
binding = new Binding();
binding.Source = address;
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
binding.Path = new PropertyPath("Addr1");
this.db_Addr1.SetBinding(TextEdit.TextProperty, binding);
...............
}
Now I want to create some universal simple engine, to fill Data values(assign values from DataTable to my class properties). Does anyone knows some way how to do that..? In example is there some way to assign values by names of properties. Lets say my property names equals to names of Columns from dataRow. Is its possible in wpf to do something like that, or not, should i assign values in every window manually?
Personally I've recourse to code generation to do the job, but you can use to Jimmy Bogard's AutoMapper, which does pretty much what you're talking about. It is on CodePlex and GoogleCode.