MyDoc.cs
public class MyDoc
{
public string Private {set;get;}
public string Public {set;get;}
}
MyFind.cs
public class MyFind
{
public string Find {set;get;}
public string News {set;get;}
private ObservableCollection<MyDoc> _list;
public ObservableCollection<MyDoc> List
{
get
{
if (_list == null)
{
_list = new ObservableCollection<MyDoc>();
}
return _list;
}
set
{
if (_list != value)
{
_list = value;
}
}
}
}
In Page1.xaml.cs
MyFind myfind = new MyFind();
myfind.Find = Findtextbox.Text;//string = string
myfind.News = Newstextbox.Text;//string = string
myfind.List = ???
ObservableCollection = listbox1.??? (??? = Items,or ItemsSources,or something,...May I use Convert ?)<------------ I don't have any ideas ! Help me !
If you've set the ItemsSource property to something like a List you could execute the following code:
MyFind myFind = new MyFind();
var myDocs = simpleListBox.ItemsSource as List<MyDoc>;
myDocs.ForEach(d => myFind.List.Add(d));
I think you're looking for the ItemsSource property:
MyFind myfind = new MyFind();
myfind.Find = Findtextbox.Text;
myfind.News = Newstextbox.Text;
myfind.List = new ObservableCollection<MyDoc>(listbox1.ItemsSource.Cast<MyDoc>());
Here I'm creating a new ObservableCollection of MyDoc objects, and to the constructor I'm passing an IEnumerable of MyDoc items. Because the listbox1.ItemsSource property returns an untyped IEnumerable, I'm first casting it using LINQ to the correct type.
Why do you want to do this is just beyond me! If you use an ObservableCollection with Binding and add remove T (items) from your listbox, the observable collection will get updated. Something inline with this:
public class MyViewModel
{
public ObservableCollection<MyData> List { get; set; }
}
public class MyView : UserControl
{
public MyView()
{
DataContext = new MyViewModel();
}
}
<ListBox ItemsSource="{Binding List}" />
Related
Just wondering as to why my ObservableCollection is not binding to my Combo Box
I don't get any errors it just doesn't populate it.
public class TableList : ObservableCollection<TableName>
{
public TableList() : base()
{
Add(new TableName(1, "Notes"));
Add(new TableName(2, "TemplateNotes"));
}
}
public class TableName
{
private int noteID;
private string noteName;
public TableName(int ID, string name)
{
this.noteID = ID;
this.noteName = name;
}
public int NoteID
{
get { return noteID; }
set { noteID = value; }
}
public string NoteName
{
get { return noteName; }
set { noteName = value; }
}
}
This is my XAML
<ComboBox
x:Name="noteSaveToSelection"
HorizontalAlignment="Left"
Height="35"
Margin="155,932,0,0"
VerticalAlignment="Top"
Width="180"
ItemsSource="{Binding TableList}"
DisplayMemberPath="NoteName"
SelectedValuePath="NoteID"/>
I am new to this so i apologise if i have missed something small.
Apparently you never create an instance of your TableList class that you can actually bind to.
Create a view model class with a TableList property, e.g. like
public class ViewModel
{
public TableList TableList { get; } = new TableList();
}
Then set the DataContext property of your MainWindow to an instance of the view model class:
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
I've seen a bunch of posts regarding databinding to databases but none of them have helped with databinding to an existing object in memory. I've also looked at several stack overflow posts where people have said the following code should've bound the properties on my combo box:
projectData = new ProjectData();
this.parentTypeComboBox.DataSource = projectData.MobList;
this.parentTypeComboBox.DisplayMember = "MobType";
this.parentTypeComboBox.ValueMember = "MobType";
My data object has public getters/setters for it's various properties and I've added the INotifyPropertyChanged interface on the classes but do not attach any listeners to the event as of now. From what I've read this should've been all I had to do to get the control to bind to my data object. Any idea why I'm not seeing my combo box get populated with data when my object list changes?
Project data class:
public class ProjectData : INotifyPropertyChanged
{
public static string PROJECT_OUTPUT_DIRECTORY = "..\\";
private List<Mob> _mobList;
public List<Mob> MobList
{
get { return _mobList; }
set { _mobList = value; OnPropertyChanged("MobList"); }
}
public ProjectData()
{
MobList = new List<Mob>();
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Mob Class:
//Snippet mob of class
public partial class Mob : IEquatable<Mob>, INotifyPropertyChanged
{
public Mob()
{
dataAttributeField = new List<MobDataAttribute>();
}
private List<MobDataAttribute> dataAttributeField;
private string mobTypeField;
private string parentTypeField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("DataAttribute")]
public List<MobDataAttribute> DataAttribute
{
get
{
return this.dataAttributeField;
}
set
{
this.dataAttributeField = value;
OnPropertyChanged("DataAttribute");
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string MobType
{
get
{
return this.mobTypeField;
}
set
{
this.mobTypeField = value;
OnPropertyChanged("MobType");
}
}
}
Using this projectData = new ProjectData(); the MobList is an empty list yet.
If you didn't populate data, you should populate your data to list to show it in ComboBox.
Remember that every time you populate data, you should update DataSource property of your ComboBox:
this.comboBox1.DataSource = parent.Childs;
If you are bound to a data source that does not implement the
IBindingList interface, such as an ArrayList, the bound control's data
will not be updated when the data source is updated. For example, if
you have a combo box bound to an ArrayList and data is added to the
ArrayList, these new items will not appear in the combo box.
Here is a sample:
public partial class SampleForm : Form
{
public SampleForm()
{
InitializeComponent();
}
private void SampleForm_Load(object sender, EventArgs e)
{
//Initialize parent and populate its Childs
var parent = new Parent()
{
ParentName = "Parent 1",
Childs = new List<Child>{
new Child(){ChildName= "Child1"},
new Child(){ChildName= "Child2"}
}
};
this.comboBox1.DataSource = parent.Childs;
this.comboBox1.DisplayMember = "ChildName";
this.comboBox1.ValueMember = "ChildName";
}
}
public class Parent
{
public Parent()
{
Childs = new List<Child>();
}
public string ParentName { get; set; }
public List<Child> Childs { get; set; }
}
public class Child
{
public string ChildName { get; set; }
}
Screenshot:
So I have a page that has a TabControl that uses multiple UserControls (each user control represents the contents of a TabItem).
I have a ComboBox in both user controls that share the same ItemsSource (OrganizationSource) and SelectedValue(OrganizationSelected) properties,
I however cannot seem to bind to ComboBox within the EventDetails UserControl, but it works flawlessly inside of the OrganizationDetails UserControl.
The OutreachMVVM is set to the DataContext for the parent page that the tabs reside in. I still have to set the datacontexts for the user controls themselves for it to work properly.
I just need to figure out how to set the binding for the ComboBox inside of the EventDetails. I saw something about dependency property but I do not understand it. I thought I would be able to set the binding for the ComboBox inside of EventDetails as the same for the ComboBox inside of OrganizationDetails, but that's not the case.
internal class OutreachMVVM : ViewModelBase
{
public OutreachMVVM()
{
EventDetails = new EventDetailsVMB();
OrganizationDetails = new OrganizationDetailsVMB();
}
public EventDetailsVMB EventDetails { get; set; }
public OrganizationDetailsVMB OrganizationDetails { get; set; }
}
EventDetailsVMB:
class EventDetailsVMB : ViewModelBase
{
private string _eventTypeSelected;
private string _zipSelected;
private readonly UserListTableAdapter _userListTableAdapter = new UserListTableAdapter();
private readonly EventTypeListTableAdapter _eventTypeListTableAdapter = new EventTypeListTableAdapter();
private readonly CityListTableAdapter _cityListTableAdapter = new CityListTableAdapter();
private readonly LocationInfoByZipTableAdapter _locationInfoByZipTableAdapter = new LocationInfoByZipTableAdapter();
public string User { get; set; }
public string EventName { get; set; }
public string Location { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string County { get; set; }
public string ServiceArea { get; set; }
//Set EventType CombBox
public ObservableCollection<string> EventTypeSource
{
get
{
var eventTypeList = _eventTypeListTableAdapter.GetEventTypeList();
var eventTypeSource = new ObservableCollection<string>();
eventTypeSource.AddRange(from DataRow row in eventTypeList.Rows select row.ItemArray[0].ToString());
return eventTypeSource;
}
}
//Set User ComboBox
public ObservableCollection<string> UserSource
{
get
{
var userList = _userListTableAdapter.GetUserList();
var userSource = new ObservableCollection<string>();
foreach (var username in Enumerable.Where(userList, username => username.Username == Environment.UserName))
{
User = username.FullName;
}
userSource.AddRange(from DataRow row in userList.Rows select row.ItemArray[0].ToString());
OnPropertyChanged("User");
return userSource;
}
}
//Set City RadAutoCompleteBox
public ObservableCollection<string> CitySource
{
get
{
var cityList = _cityListTableAdapter.GetCityList();
var citySource = new ObservableCollection<string>();
citySource.AddRange(from DataRow row in cityList.Rows select row.ItemArray[0].ToString());
return citySource;
}
}
public string EventTypeSelected
{
get { return _eventTypeSelected; }
set
{
_eventTypeSelected = value;
OnPropertyChanged("EventTypeSelected");
}
}
public string ZipSelected
{
get { return _zipSelected; }
set
{
_zipSelected = value;
var locationInfo = _locationInfoByZipTableAdapter.GetLocationInfoByZip(_zipSelected);
if (locationInfo.Rows.Count != 0)
{
City = locationInfo.Rows[0].ItemArray[0].ToString();
State = locationInfo.Rows[0].ItemArray[1].ToString();
County = locationInfo.Rows[0].ItemArray[2].ToString();
ServiceArea = locationInfo.Rows[0].ItemArray[3].ToString();
}
else if (ZipSelected.Length == 5) {}
else
{
City = "";
State = "TX";
County = null;
ServiceArea = null;
}
OnPropertyChanged("City");
OnPropertyChanged("State");
OnPropertyChanged("County");
OnPropertyChanged("ServiceArea");
}
}
}
OrganizationDetailsVMB:
class OrganizationDetailsVMB : ViewModelBase
{
private string _organizationName;
private string _street1;
private string _street2;
private string _city;
private string _state;
private string _zip;
private string _county;
private string _serviceArea;
private bool _cbo;
private bool _fbo;
private bool _mo;
private bool _sbo;
private bool _sno;
private readonly OrganizationListTableAdapter _organizationListTableAdapter = new OrganizationListTableAdapter();
private readonly OrgByNameTableAdapter _orgByNameTableAdapter = new OrgByNameTableAdapter();
private readonly OrgTypeByOrgNameTableAdapter _orgTypeByOrgNameTableAdapter = new OrgTypeByOrgNameTableAdapter();
public string OrganizationSelected
{
get { return _organizationName; }
set
{
_organizationName = value;
var organizationQueryResults = _orgByNameTableAdapter.GetOrganizationByName(_organizationName);
var orgTypeQueryResults = _orgTypeByOrgNameTableAdapter.GetOrgTypeByName(_organizationName);
if (organizationQueryResults.Rows.Count != 0)
{
OrgStreet1Value = organizationQueryResults.Rows[0].ItemArray[1].ToString();
OrgStreet2Value = organizationQueryResults.Rows[0].ItemArray[2].ToString();
OrgCityValue = organizationQueryResults.Rows[0].ItemArray[3].ToString();
OrgStateValue = organizationQueryResults.Rows[0].ItemArray[4].ToString();
OrgZipValue = organizationQueryResults.Rows[0].ItemArray[5].ToString();
OrgCountyValue = organizationQueryResults.Rows[0].ItemArray[6].ToString();
OrgServiceAreaValue = organizationQueryResults.Rows[0].ItemArray[7].ToString();
CBO = Convert.ToBoolean(orgTypeQueryResults.Rows[0].ItemArray[1]);
FBO = Convert.ToBoolean(orgTypeQueryResults.Rows[0].ItemArray[2]);
SBO = Convert.ToBoolean(orgTypeQueryResults.Rows[0].ItemArray[3]);
MO = Convert.ToBoolean(orgTypeQueryResults.Rows[0].ItemArray[4]);
SNO = Convert.ToBoolean(orgTypeQueryResults.Rows[0].ItemArray[5]);
}
else
{
OrgStreet1Value = "";
OrgStreet2Value = "";
OrgCityValue = "";
OrgStateValue = "";
OrgZipValue = "";
OrgCountyValue = "";
OrgServiceAreaValue = "";
CBO = false;
FBO = false;
SBO = false;
MO = false;
SNO = false;
}
}
}
public ObservableCollection<string> OrganizationSource
{
get
{
var organizationList = _organizationListTableAdapter.GetOrganizationList();
var organizationSource = new ObservableCollection<string>();
organizationSource.AddRange(from DataRow row in organizationList.Rows select row.ItemArray[0].ToString());
return organizationSource;
}
}
public string OrgStreet1Value
{
get { return _street1; }
set
{
if (_street1 != value)
{
Validator.ValidateProperty(value,
new ValidationContext(this, null, null) { MemberName = "OrgStreet1Value" });
_street1 = value;
OnPropertyChanged("OrgStreet1Value");
}
}
}
public string OrgStreet2Value
{
get { return _street2; }
set
{
if (_street2 != value)
{
Validator.ValidateProperty(value,
new ValidationContext(this, null, null) { MemberName = "OrgStreet2Value" });
_street2 = value;
OnPropertyChanged("OrgStreet2Value");
}
}
}
public string OrgCityValue
{
get { return _city; }
set
{
if (_street1 != value)
{
Validator.ValidateProperty(value,
new ValidationContext(this, null, null) { MemberName = "OrgCityValue" });
_city = value;
OnPropertyChanged("OrgCityValue");
}
}
}
public string OrgStateValue
{
get { return _state; }
set
{
if (_state != value)
{
Validator.ValidateProperty(value,
new ValidationContext(this, null, null) { MemberName = "OrgStateValue" });
_state = value;
OnPropertyChanged("OrgStateValue");
}
}
}
public string OrgZipValue
{
get { return _zip; }
set
{
if (_zip != value)
{
Validator.ValidateProperty(value,
new ValidationContext(this, null, null) { MemberName = "OrgZipValue" });
_zip = value;
OnPropertyChanged("OrgZipValue");
}
}
}
public string OrgCountyValue
{
get { return _county; }
set
{
if (_county != value)
{
Validator.ValidateProperty(value,
new ValidationContext(this, null, null) { MemberName = "OrgCountyValue" });
_county = value;
OnPropertyChanged("OrgCountyValue");
}
}
}
public string OrgServiceAreaValue
{
get { return _serviceArea; }
set
{
if (_serviceArea != value)
{
Validator.ValidateProperty(value,
new ValidationContext(this, null, null) { MemberName = "OrgServiceAreaValue" });
_serviceArea = value;
OnPropertyChanged("OrgServiceAreaValue");
}
}
}
public bool CBO
{
get { return _cbo; }
set
{
_cbo = value;
OnPropertyChanged("CBO");
}
}
public bool FBO
{
get { return _fbo; }
set
{
_fbo = value;
OnPropertyChanged("FBO");
}
}
public bool SBO
{
get { return _sbo; }
set
{
_sbo = value;
OnPropertyChanged("SBO");
}
}
public bool MO
{
get { return _mo; }
set
{
_mo = value;
OnPropertyChanged("MO");
}
}
public bool SNO
{
get { return _sno; }
set
{
_sno = value;
OnPropertyChanged("SNO");
}
}
}
EventDetailsTab:
<TabItem Header="Event Details" x:Name="EventDetailsTab"
Style="{StaticResource TabStyle}"
DataContext="{Binding EventDetails}">
<eventTabs:_1_EventDetailsTab />
</TabItem>
OrganizationDetailsTab:
<TabItem Header="Organization" x:Name="OrganizationTab"
Style="{StaticResource TabStyle}"
DataContext="{Binding OrganizationDetails}">
<eventTabs:_2_OrganizationTab />
</TabItem>
As I said the bindings work flawlessly overall, but I want to reference a binding associated with OrganizationDetails for a control that resides in both the EventDetailsTab and OrganizationDetailsTab.
The code for that item is as follows...
<ComboBox Name="OrgNameComboBox" ItemsSource="{Binding OrganizationSource}"
SelectedValue="{Binding OrganizationSelected,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
You're setting the DataContext for your event details tab to {Binding EventDetails} and the DataContext for your organization tab to {Binding OrganizationDetails}, but the OrganizationSource and OrganizationSelected fields that your ComboBoxes are binding to only exist in the OrganizationDetailsVMB class. A quick hack would be to change your event details ComboBox to point to the correct place with a RelativeSource binding back to the TabItem's DataContext and down again to the OrganizationDetails:
<ComboBox Name="OrgNameComboBox" ItemsSource="{Binding OrganizationSource}"
DataContext="{Binding RelativeSource={RelativeSource AncestorType=TabControl}, Path=DataContext.OrganizationDetails}"
SelectedValue="{Binding OrganizationSelected,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
To be perfectly honest though I think you need to clean up your architecture. Your view model appears very tightly coupled to your underlying data model instead of the view, to the point where you're even accessing your table adapters in your getters which means A) you have no way of doing session management, B) your view performance will now be throttled by your DAL and you'll start having performance issues, and C) trying to introduce any type of multi-threading will cause all manner of access conflicts in your ORM.
A)
This way is good when you want have some data (like a combobox info) across an App or Multi Window:
Create 3 ViewModel (all inherited from INotifyPropertyChanged).
OrganizationViewModel: INCLUDE OrganizationSource and OrganizationSelected
OrganizationDetailsViewModel: WHITHOUT OrganizationSource and OrganizationSelected
OrganizationEventsViewModel: WHITHOUT OrganizationSource and OrganizationSelected
Now you can create a simple Static class named GeneralData & make a static property in it of OrganizationViewModel type like this:
public static class GeneralData{
public static OrganizationViewModel Organization {get;set;}
}
In the App.xaml.cs fill the Organization property of the GeneralData class with a new instance of OrganizationViewModel.
Ok... Now we have every things we need to start playing....
Every time you want to fill the ComboBox you should use the Organization [static property] of GeneralData class like this:
<ComboBox Name="OrgNameComboBox"
DataSource="{Binding Source={x:Static GeneralData.Organization}}"
ItemsSource="{Binding Source={x:Static GeneralData.Organization.OrganizationSource}}"
SelectedValue="{Binding Source={x:Static GeneralData.Organization.OrganizationSelected,
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
And every time you want check which item of the Combobox is selected in code-behind (such as inside the ViewModels) you can easily check it like this:
var selectedOrganisation = GeneralData.Organization.OrganizationSelected;
Note: i recommend to you before closing the window that include the ComboBox run this code (to make sure there is not any alive reference to the static property):
BindingOperations.ClearAllBindings(OrgNameComboBox);
B)
If you have just 1 window include 2 UserControl then prevent static properties and instead of above way use this way:
Create 3 ViewModel (all inherited from INotifyPropertyChanged).
OrganizationViewModel: INCLUDE OrganizationSource and OrganizationSelected
OrganizationDetailsViewModel: WHITHOUT OrganizationSource and OrganizationSelected
OrganizationEventsViewModel: WHITHOUT OrganizationSource and OrganizationSelected
Now easily implement this scenario:
In Window1.xaml.cs:
Window1.DataSource= new OrganizationViewModel();
In EventUserControl.xaml.cs:
EventUserControl.DataSource= new OrganizationEventsViewModel();
In OrganizationDetailsUserControl.xaml.cs:
EventUserControl.DataSource= new OrganizationDetailsViewModel();
Now create a DependencyProperty in both EventUserControl and OrganizationDetailsUserControl to give them the SelectedItem of ComboBox. Your property type should be string. you can create the DependencyPropertys base on this tutorial.
For example use this name for your DependencyPropertys in both UserControls: SelectedOrganisation
OK, put the Combobox in the Window1.xaml (NOT inside any UserControl).
Now we fill these SelectedOrganisations from outer their UserControls like the following codes.
In Window1.xaml
<uc.OrganizationDetailsUserControl
SelectedOrganisation="{Binding ElementName=OrgNameComboBox, Path=SelectedItem}"/>
<uc.EventUserControl
SelectedOrganisation="{Binding ElementName=OrgNameComboBox, Path=SelectedItem}"/>
Now you have the SelectedItem of the ComboBox inside your UserControl you can play with it inside the UserControls and call some methods of the ViewModels with SelectedOrganisation as method parameter.
The route I took is the MVVM Light Toolkit.
public class MyDoc
{
public string Private {set;get;}
public string Public {set;get;}
}
public class MyFind
{
public string Find {set;get;}
public string News {set;get;}
private ObservableCollection<MyDoc> _smalllist;
public ObservableCollection<MyDoc> SmallList
{
get
{
if (_smalllist == null)
{
_smalllist = new ObservableCollection<MyDoc>();
}
return _smalllist;
}
set
{
if (_smalllist != value)
{
_smalllist = value;
}
}
}
}
public class Ask
{
private ObservableCollection<MyFind> _Biglist;
public ObservableCollection<MyFind> BigList
{
get
{
if (_Biglist == null)
{
_Biglist = new ObservableCollection<MyFind>();
}
return _Biglist;
}
set
{
if (_Biglist != value)
{
__Biglist = value;
}
}
}
}
How can i save IsolatedStorage the Small list, and Big list ?
("Important : into the BigList need got 2 string and 1 ObservableCollection<> ").
We can see in class MyFind has got an ObservableCollection and 2 string in class MyAsk has got an ObservableCollection
You need to create your own serializable observable collection as this: Check this http://kentb.blogspot.com/2007/11/serializing-observablecollection.html
another option is to crate IList backing fields and create a wrapping ObservableCollection properties marked as Non-Serializable
Should it be possible to bind a WPF combo box to a class. I have a class that implements IEmunerable and IEnumerator, and contains a list of objects, as follows:
class MyClass
{
public string Title { get; set; }
public string Directory { get; set; }
public MyClass(string title, string directory)
{
Title = title;
Directory = directory;
}
}
class MyClasses : IEnumerable, IEnumerator
{
private List<MyClass> allClasses;
private int position = 0;
public List<MyClass> GetClasses()
{
allClasses = new List<MyClass>()
{
new MyClass("example1", "dir1"),
new MyClass("example2", "dir2")
};
return allClasses;
}
public IEnumerator GetEnumerator()
{
return (IEnumerator) this;
}
public object Current
{
get
{
return allClasses[position];
}
}
public bool MoveNext()
{
position++;
return (position < allClasses.Count());
}
public void Reset()
{
position = -1;
}
}
So now I want to bind this to a WPF combobox. Here’s what I have, which doesn’t work (I instead get a list of type names of the objects):
allClasses.GetClasses();
cboTest.ItemsSource = allClasses;
cboTitle.SelectedValue = "Title";
Can anyone tell me how to implement this binding?
cboTitle.SelectedValue = "Title";
should be
cboTitle.DisplayMemberPath = "Title";
Change
cboTitle.SelectedValue = "Title";
to
cboTitle.DisplayMemberPath = "Title";