Unable binding from class on C# - wpf

Here is code of class:
public class listboxitem
{
public string textmenu { get; set; }
public string logomenu { get; set; }
}
But when im binding it on textbox that's not show...
I have these array:
private string[] Logo_menu_array = { "/Assets/star-6-48.ico", "/Assets/note-48.ico", "/Assets/note-48.ico", "medal-48.ico", "joystick-48.ico" };
private string[] Text_menu_array={"Phổ biến trên YouTuBe","Âm nhạc","Thể thao","Trò chơi"};
//load menu
public void Load_Menu()
{
List<listboxitem> text = new List<listboxitem>();
listboxitem items=new listboxitem();
for(int i=0;i<Text_menu_array.Length&& i<Logo_menu_array.Length;i++)
{
items.textmenu=i.ToString();
}
for(int j=0;j<Logo_menu_array.Length;j++)
{
items.logomenu = j.ToString();
}
text.Add(items);
}
This website didn't agreed show more code. Ready hard to ask these my question.
I added code:
<ListBox Name="lst_menu" Foreground="Red">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Image Source="{Binding logomenu}"></Image>
<TextBlock Text="{Binding textmenu}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And here to loaded:
public MainPage()
{
this.InitializeComponent();
//get menu
List<listboxitem> menu_list = new List<listboxitem>();
Load_Menu();
lst_menu.ItemsSource = menu_list;
}

A few things here...
Firstly, we need to see the XAML to see how you are binding this in your UI. I'm going to assume you have something like:
<ListBox ItemSource="{Binding Items}"/>
Then a template that presents these.
In your code you have a List object called text which exists only in your method. You need to assign this value to a property in your view model onto which you can bind - based on the above:
public List<ListItem> Items {get;set;}
This property should trigger PropertyChanged as defined in INotifyPropertyChanged so implement that on your class. Implementing INotifyPropertyChanged
That gets you the basics. If you want to dynamically control this collection - i.e. change items at runtime - you should investigate ObservableCollection.
EDIT:
Based upon your full code listing, using code behind. You are setting your lst_menu.ItemsSource to an empty List. Your Load_Menu() builds a collection but does not return it.
public List<listboxitem> Load_Menu()
{
List<listboxitem> text = new List<listboxitem>();
listboxitem items=new listboxitem();
for(int i=0;i<Text_menu_array.Length&& i<Logo_menu_array.Length;i++)
{
items.textmenu=i.ToString();
}
for(int j=0;j<Logo_menu_array.Length;j++)
{
items.logomenu = j.ToString();
}
text.Add(items);
return text;
// Note you will only ever return one item here - check the logic
}
Then in your constructor:
List<listboxitem> menu_list = Load_Menu();
lst_menu.ItemsSource = menu_list;
Assuming you want the arrays to be used to build your collection, try using the following for build menu:
List<listboxitem> text = new List<listboxitem>();
for(int i =0; i< Math.Min(Logo_menu_array.Length, Text_menu_array.Length, i++)
{
var l = new listboxitem();
l.logomenu = Logo_menu_array[i];
l.textmenu = Logo_menu_array[i];
}
return text;
I hope this helps.

Related

Bind a class member to a listbox

I am a beginner in wpf. In one of my projects I have a frmField class as bellow:
public class frmFields
{
public bool succelssfulEnd = true;
public string fileName;
public List<string> errList = new List<string>();
}
and a list
<ListBox Name="LSTErrors" Grid.Row="11" Grid.Column="1" Grid.ColumnSpan="2" ItemsSource ="{Binding}" SelectionChanged="LSTErrors_SelectionChanged" />
I need to bind errList to the above listBox in such a way that any change in the List is reflected on the ListBox.
Is there anyone to guide me?
You need an ObservableCollection to refresh the UI every time it changes.
public class frmFields
{
public bool succelssfulEnd = true;
public string fileName;
private ObservableCollection<String> _errList = new ObservableCollection<String>();
public ObservableCollection<String> ErrList {
get {return _errList;}
set {
_errList = value;
//your property changed if you need one
}
}
}
Note that you can only bind to a Property or a DependencyProperty, not a simple public variable like you tried.
In your constructor you'll need to add:
this.DataContext = this;
or in your XAML:
DataContext="{Binding RelativeSource={RelativeSource self}}"
In your root element. And then bind ItemsSource like this:
<ListBox ItemsSource="{Binding ErrList, Mode=OneWay}">
...
</ListBox>

Switching the Binding Source of DataGrid in WPF

In my view there is a DataGrid and its ItemsSource is bound to a Filelist from 3 different folders.
Is it possible to switch the binding source programatically?
E.g. for the first click ItemsSource="{Binding FileList}
and for the second click ItemsSource="{Binding FileList1}
Is this possible in the same DataGrid? I'm following MVVM and i use Prism.
Yes it is possible to change the data context on click or on some other action..
You said that you are using MVVM prism... here is a sample i have created to assist you..
In this sample my source(in your case it is datagrid) itemssource property will always binded to a property "Sourcelist" and on click i am re assigning the Sourcelist to diffrent list..
so on every click we are reassigning the sourcelist property which is binded to datagrid or list
class Viewmodel : ViewModelBase
{
public Viewmodel()
{
ChangeDataSource = new DelegateCommand<object>(ChagneDataSource);
Filelist1 = new FileListOne();
FileList2 = new FileListTwo();
Filelist1.Files = new List<string>();
FileList2.Files = new List<string>();
for (int i = 0; i < 10; i++)
{
Filelist1.Files.Add("FileListOne " + i);
FileList2.Files.Add("FileListTwo " + i);
}
Sourcelist = Filelist1;
}
private object _sourcelist;
public object Sourcelist
{
get
{
return _sourcelist;
}
set
{
_sourcelist = value;
OnPropertyChanged("Sourcelist");
}
}
public ICommand ChangeDataSource { get; set; }
public FileListOne Filelist1 { get; set; }
public FileListTwo FileList2 { get; set; }
private void ChagneDataSource(object seder)
{
if (Sourcelist.GetType() == typeof(FileListOne))
Sourcelist = FileList2;
else
Sourcelist = Filelist1;
}
}
class FileListOne
{
public List<string> Files { get; set; }
}
class FileListTwo
{
public List<string> Files { get; set; }
}
XAML
<StackPanel>
<ListBox x:Name="listbox2" ItemsSource="{Binding Sourcelist.Files}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button x:Name="button" Content="Button" Command="{Binding ChangeDataSource}"/>
</StackPanel>
Those XAML snippets just translate to
dataGrid.SetBinding(DataGrid.ItemsSourceProperty, new Binding("FileList"));
You need to keep track of how many clicks have occurred in a field, further you need to have a reference to the DataGrid of course. (You could create one via x:Reference and store that in the Button's Tag or CommandParameter if you use commands which would be more likely with MVVM i suppose)

How to set itemsource for DataGrid to some array from ViewModel

Here is my try :
<DataGrid
Grid.Row="0"
AutoGenerateColumns="True"
ItemsSource="{Binding Path = Workers}"
Grid.ColumnSpan="1"
Name="DataGrid">
</DataGrid>
private Worker[] workers;
public Worker[] Workers
{
get
{
if (IsInDesignMode) return null;
return serviceAgent.ParseFile("dataWorkers.xml").ToArray() ;
}
set
{
workers = value;
NotifyPropertyChanged(m => m.Workers);
}
}
But my DataGrid still being empty. What am I doing wrong ?
Works as advertised for me. The following results in an auto-populated editable sortable grid for me. So first begin by faking the workers array as shown below and see if it works.
If yes, investigate your ParseFile method. If not, look if you have data binding setup correctly - work to get the fake array into the view first.
XAML
=
<StackPanel>
<DataGrid AutoGenerateColumns="True"
ItemsSource="{Binding Path = Workers}"
x:Name="DataGrid"/>
Code-behind
=
public class Worker {
public int Id { get; set; }
public string Name { get; set; }
}
public class MainViewModel
{
public Worker[] Workers {
get {
return new[]{
new Worker {Id = 1, Name = "Cristiano"},
new Worker {Id = 2, Name = "Lionel"},
new Worker {Id = 3, Name = "Xavi"}
};
}
} ....
Try using a DataSet or DataTable as ItemsSource. Or use ListBox instead.
Also, here is another practice you can try:
http://msdn.microsoft.com/en-us/library/system.windows.controls.datagrid.itemssource(VS.95).aspx#Y428
It works for me.

How to bind ObservableCollection<T> on Datagrid?

I'm David. I don`t know to bind collection to datagrid in XAML for a WPF application.
below are classes.
class TestSetting(): INotifyChanged
{
private a
public double A
{
get a;
set a = value;
Notify("A");
}
private b
public double B
{
get b;
set b = value;
Notify("B");
}
private c
public double C
{
get c;
set c = value;
Notify("C");
}
}
class TestCollect():ObservableCollection<T> ,INotifyListener
{
}
above code is Psedo code.
DataContext has 7 items. So the grid will have 7 columns. Could someone please help me with an example or a code snippet.
If the datacontext contains a TestCollection, all that is needed is Setting the ItemsSource to {Binding}
I think that what you need is something like that :
Your viemodel :
public class ViewModel
{
public ViewModel()
{
SourceList = new ObservableCollection<BusinessAdapter>();
for (int i = 0; i < 50; i++)
{
SourceList.Add(new BusinessAdapter { BusinessProperty = "blabla_" + i });
}
}
public ObservableCollection<BusinessAdapter> SourceList { get; private set; }
}
You're view code behind
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
DataContext = new ViewModel();
}
}
And then in your view. The important stuff here is ' ItemsSource="{Binding SourceList}" ' which basically means "the source collection of my listbox is the the collection of my datacontext (which is a Viewmodel object) named SourceList"
<ListView x:Name="listOne"
Grid.Column="0"
Width="50"
Height="200"
ItemsSource="{Binding SourceList}" />
I am a newbie, but I will venture my answer:
ObservableCollection<YourModel> yourdata = new ObservableCollection<YourModel>();
dataGrid.ItemsSource = yourdata;
The 2nd. statement performs the binding.

Creating a dynamic checkboxes against the list of items using mvvm light wpf?

I have the following scenario:
I have one window say MainWindow where I am displaying the list of activities as per the specific user from the database. There is a one button present on the window. By clicking on that button a new window is getting opened having all the list of activities from the master table. Now I want add a chechbox on the second window against each item dynamically so that user can select/deselect the activities. Those selected/deselected values should save in the database and Parent/MainWindow should refreshed after clicking on the done button and changes should reflect in the MianWindow. But I am not getting how to dynamically creating the checkboxes against each list item and binding with the xaml and select/deselect the checkbox.
Kindly suggest with samples or examples.
Thanks
You can customize your listviewitem using the ListView's ItemTemplate. Add a checkbox
and a textblock to a panel which would constitute your datatemplate.
Update
The Model:
public class Activity
{
public Activity(int id, string name)
{
ID = id;
Name = name;
}
public int ID { get; set; }
public string Name { get; set; }
}
The ViewModel for ListViewItem in Second Window:
public class ActivityViewModel
{
Activity _model;
public ActivityViewModel(Activity model, bool isSelected)
{
_model = model;
IsSelected = isSelected;
}
public string Name { get { return _model.Name; } }
/* Since the view has a checkbox and it requires a bool value for binding
we create this property */
public Nullable<bool> IsSelected { get; set; }
}
The DataAccess
public class DaoDailyActivities
{
string activityName = "";
bool IsSelected;
SqlConnection con = new SqlConnection("server=172.16.32.68;database=ParentalHealth;uid=sa;pwd=Emids123");
public IEnumerable<Activity> GetActivities()
{
SqlCommand cmd = new SqlCommand("SP_GetActivities", con);
cmd.CommandType = CommandType.StoredProcedure;
con.Open(); /* It is safe to open connections in a try block */
SqlDataReader readerActivities = cmd.ExecuteReader();
while (readerActivities.Read())
{
yield new Activity(readerActivities["ActivityID"].ToString(), readerActivities["ActivityName"].ToString());
}
}
}
The ViewModel for SecondWindow:
public class SecondWindowViewModel : ViewModelBase
{
DaoDailyActivities _rep = new DaoDailyActivities();
public ObservableCollection<ActivityViewModel> AllActivities { get; set; }
public SecondWindowViewModel()
{
LoadAllActivities();
}
LoadAllActivities()
{
foreach(Activity activity in _rep.GetActivities())
{
AllActivities.Add(new ActivityViewModel(activity, (activity.ID % 2 == 0)));
}
}
}
The XAML:
<ListView ItemsSource="{Binding AllActivities}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=Name}" />
<CheckBox IsChecked="{Binding Path=IsSelected}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListView>

Resources