how can I bind ID property to checkbox in xaml WUP - c#

First thank you guys in StackOverFlow to give the opportunity, u guys doin really great job, I'm very beginner in windows 10 universal apps, I created app which has employee class for example in the models folder let us say like the following:
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
}
and in xaml I created AutoSuggestBox and listView which I bind to ObervableCollection list of type Employee and this as the following:
<ListView ItemsSource="{x:Bind EmployeesList}"
HorizontalAlignment="Left">
<ListView.ItemTemplate>
<DataTemplate x:DataType="data:Employee">
<StackPanel Orientation="Horizontal">
<CheckBox Checked="StatusCB_Checked"
Margin="5,2,5,0"/>
<TextBlock Name="EmpNametxtBlk"
Text="{x:Bind Name}"
VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Now once I type name in the AutoSuggestBox the list view will show the checkBox and the employee name , I want to check the checkbox and I want to get the employee object to get deleted from the list view and then add to another list view let's say for chosen employees , my questions is how I can bind the checkBox to the employee ID and then i can use that object in the code behind for the check event ? I mean once i check the checkbox of any added employee on the Listview I wanted to do :
deleted that employee from the ListView and add him in other list view
the other list view will be hidden till I delete employees from the first Listview.
how I can bind the checkbox to the ID of the employee and how I can extract the employee object in the check event or any other even, well I wish I explained what I want in clear way !

how I can extract the employee object in the check event or any other even
You can get the object from DataContext property of the sender object (just make sure you cast the sender from object to FrameworkElement type first)

As #thang2410199 said
You can get the object from DataContext property of the sender object.
You don't need bind the Id property to somewhere for deleting since you can get the employee instance from checkbox's DataContext property. You can delete the checked employee using the following code:
private void StatusCB_Checked(object sender, RoutedEventArgs e)
{
var checkbox = sender as CheckBox;
if(checkbox!=null)
{
var employee =(Employee)checkbox.DataContext;
Employeeslist.Remove(employee);
}
}
A completed demo to meet your requirements you can download here. More details about Listview reference the official sample.

For your list you should use an ObservableCollection.
Implement the INotifyPropertyChanged Interface so the UI is getting notified when data is changing.
Create a new class called ListCountToVisibilityConverter.cs, Implement the IValueConverter interface. When the count of your
Observable collection is > 0 return Visibility.Visible else return
Visibility.Collapsed .
You can delete Items by getting the selected index in the ListView and you can add items by using the add method of the observable collection.
You may want to implement the MVVM pattern. MVVM Wikipedia

Related

An ItemTemplate Containing A Combobox - How Do I Bind To The SelectedValue?

Imagine your working on a UI for an Wedding Planner app. You'll have a list of guests and you want to display their name on the screen next to a combobox containing values of 'Will Attend' / 'Maybe' / 'No'.
I've tried to something just that....I have a collection of items inside a view model (the guests). For each of those items I want to display a Label and a ComboBox. Each ComboBox has the same values in the drop down (the possible responses).
I've created an ItemTemplate that contains a label and a combobox. I bind it to my collection of guests and it works as expected. I'm using ancestor binding so that the ComboBox's ItemsSource is bound to the list of possible responses. That works great.
What I'm struggling with is how to bind the SelectedItem to get the values the user selects? I want to have a collection of selected values on the ViewModel somehow, but I'm having a lot of trouble finding the correct words to describe this / search for it.
Can anyone help me? Am I going about this the wrong way?
You may create an enum for the attendance state and add an Attendance property to your Guest class:
public enum Attendance
{
Yes,
No,
Maybe
}
public class Guest
{
...
public Attendance Attendance { get; set; } // raise PropertyChanged event if necessary
}
Now you could set the Tag property of the ComboBox items to the appropriate enum value and bind the SelectedValue property:
<ItemsControl.ItemTemplate>
<DataTemplate>
<ComboBox SelectedValue="{Binding Attendance}" SelectedValuePath="Tag">
<TextBlock Tag="Yes">Will Attend</TextBlock>
<TextBlock Tag="No">Won't Attend</TextBlock>
<TextBlock Tag="Maybe">May Attend</TextBlock>
</ComboBox>
</DataTemplate>
</ItemsControl.ItemTemplate>

How do I display the first item in my ComboBox based on my dataBinding?

Xaml:
<ComboBox Grid.Row="1"
Name="CmbClasse"
Grid.Column="3"
Margin="5,5,5,5"
ItemsSource="{Binding DataContext.Classeses}"
SelectedValuePath="ClasseId"
DisplayMemberPath="ClasseName"
SelectedValue="{Binding DataContext.CurrentSelectedPersonagem.IdClasse, Mode=TwoWay}"/>
When I open my application, the ComboBox do not have display any default item. But the item list is working, have all the items on it. Please help, if a image is needed just ask.
Thanks.
Here is a method I use all the time.
Firstly, your View Model should have two properties, one to represent the collection, and the other to represent the selected item.
public IEnumerable<YourObject> MyObjects { get; private set; }
public YourObject SelectedObject { get; private set; }
Note: It would be a good idea to use an ObservableCollection for MyObjects, and also implement INotifyPropertyChanged. Use this only if you need to create brand new instances of your collection in the View Model.
Your ComboBox should then bind to these properties, like so:
<ComboBox ItemsSource="{Binding MyObjects}"
SelectedItem="{Binding SelectedObject}"
...
/>
Now, here comes the magic. When you create your collection, simply set the SelectedObject to be the FirstOrDefault item in the list.
private void LoadData()
{
//TODO: Load the data into the collection
//Set the first item
this.SelectedObject = MyObjects.FirstOrDefault();
}
This will ensure that the first item is always selected. You do not need to implement INotifyPropertyChanged on the SelectedObject property unless you are planning on manually changing the value of this property in your View Model.

How to populate LongListSelector

I'm starting out with C# Windows Phone 8 development and I am trying to write an app which uses a LongListSelector. The app will show a long list of train station names.
I have been looking at some of the samples online, including the MSDN PeopleHub, and PhotoHub samples but they seem very complex. I took the PeopleHub sample and hacked at it a bit until I got it to display a list of stations in a LongListSelector but I wasn't able to find out which item had been selected in the list. The SelectedItem property was just returning the app name when passed to another page and not which item had been picked in the list.
I think I need a basic example of how to add some items to a LongListSelector and then find and pass the selected item to another page. I don't fully understand how the control works, if you have to use some sort of DataBinding with the LongListSelector to populate it or whether it's something simpler like:
LongListSelectorThing.add("trainstationA");
LongListSelectorThing.add("trainstationB");
LongListSelectorThing.add("trainstationC");
etc
Can someone give me some simple basic pointers as to how to populate this control and find out which item the user selects? When I say which item they select, when the LongListSelector grid appears, they click on A for example, and it then shows a list of things beginning with A and they then click on trainstationA, I'd want to be able to detect they've picked trainstationA and pass that info to another page so I can display further information about it.
Sorry for if this seems basic, I'm quite new to this.
Thanks!
Here is a basic example which should help you understand:
First in your Page (xaml file) you define the control LongListSelector (LLS):
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<phone:LongListSelector Name="myLLS" Margin="0">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
</Grid>
You also declare how its Items will look like. It can be any UIElement - a button, Image, Grid and so on. In the code above I declared that my Item would be a TextBlock which content (text) I've bound to a property 'Name'. I've also given the LLS a name, that I can refer to it later.
In Page.cs code you populate the LLS. Lets create the simple Station class, and populate LLS:
public class Station
{
private string _stationName;
public string Name
{
get { return _stationName; }
set { _stationName = value; }
}
public Station(string station)
{
this.Name = station;
}
}
public partial class MainPage : PhoneApplicationPage
{
ObservableCollection<Station> trainStations = new ObservableCollection<Station>();
public MainPage()
{
InitializeComponent();
myLLS.ItemsSource = trainStations;
trainStations.Add(new Station("Germany"));
trainStations.Add(new Station("France"));
trainStations.Add(new Station("Italy"));
}
}
What is important:
look that in my Station class there is property called 'Name' - that's the one to which content of the TextBlock is bound.
I've created ObservableCollection which is a collection of my Stations - it's similar to a List but when the new item is added or removed the PropertyChanged event is raised and therefore your LongListSelector can be automatically updated when you add a new station.
I've assigned created collection to myLLS.ItemsSource - it means that created LLS will be populated with Items (described in xaml as DataTemplate) and a Source of this items is that collection.
Hope this helps. Happy coding.

Updating the DisplayMember of a ListBox

This question deals with a dinky little Winforms GUI. Let it be known that I have basic knowledge of data bindings and INotifyPropertyChanged and use both in my ViewModels in WPF. But I don't know Winforms. This is for a school assignment.
So I have a class that has a DisplayName property. I also have a ListBox whose Items are a sequence of instances of my class. I have pointed myListBox.DisplayMember = "DisplayName"; After changing a value in an instance of my class that will cause the DisplayName property to return a different value, how do I tell my ListBox to pull the DisplayName property again to refresh its value?
I needed to do the same thing but with a combobox. The workaround I found is to clear and reset the DisplayMember property.
This worked:
myComboBox.DisplayMember = null;
myComboBox.DisplayMember = "DisplayName";
It's important to note that this is perhaps not the best solution as it will cause multiple SelectedValueChanged events but the end result is successful.
Doing it this way probably requires re-binding the listbox, loosing selectedIndex etc.
One workaround is to forget about the DisplayMember property and handle the Format event of the ListBox instead. Something like (from memory) :
// untested
e.Value = (e.Item as MyClass).DisplayValue;
I know this was ages ago but I had similar problem and could not find satisfying solution and finally solved with this single line at the end after updating the values:
bindingsource.EndEdit();
Items on listbox reflects any changes entered into textboxes after Update button clicked. So after lines like this:
textbox1.DataBindings["Text"].WriteValue();
textbox2.DataBindings["Text"].WriteValue();
just insert this line:
bindingsourcevariable.EndEdit();
Hope this helps others who also encounter similar problem but haven't found the right solution
Here is solution code that does everything in XAML as opposed to back end C#. This is how I do my projects utilizing MVVM (minimizing the back end code, and if possible having no back end code)
<ListBox x:Name="lstServers" HorizontalAlignment="Left" Height="285" Margin="20,37,0,0" VerticalAlignment="Top" Width="215"
ItemsSource="{Binding Settings.Servers}"
SelectedItem="{Binding Settings.ManageSelectedServer, Mode=TwoWay}"
DisplayMemberPath="UserFriendlyName"/>
This is a listbox on the Window. The keys to point out here, which can be very tricky, are the usual ItemsSource property being set to a Settings object on my view model, which has a Servers Observable collection.
Servers is a class that has a property called UserFriendlyName.
public sealed class AutoSyncServer : ObservableModel
{
public AutoSyncServer()
{
Port = "80";
UserFriendlyName = "AutoSync Server";
Server = "localhost";
}
private string _userFriendlyName;
public string UserFriendlyName
{
get { return _userFriendlyName;}
set
{
_userFriendlyName = value;
OnPropertyChanged("UserFriendlyName");
}
}
This is a partial code snippet for you of the class itself.
The SelectedItem of the ListBox is bound to an instance of the Selected object that I store in the model view called ManageSelectedServer.
The tricky part here is the DisplayMemberPath is set to "UserFriendlyName" as opposed to "{Binding UserFriendlyName}". This is key
If you use {Binding UserFriendlyName} it will display the UserFriendlyNames in the collection but will not reflect any changes to that property.
The XAML for the TextBox where the user can update the user friendly name (which should change the text in the listbox also) is:
<TextBox x:Name="txtDisplayName" HorizontalAlignment="Left" Height="23" Margin="395,40,0,0" TextWrapping="Wrap"
Text="{Binding ElementName=lstServers,Path=SelectedItem.UserFriendlyName, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Top" Width="240"/>
This sets the Text property of the TextBox and binds it to the ListBox element lstServers SelectedItem property UserFriendlyName. I've also included an UpdateSourceTrigger=PropertyChanged so that any changes made to the text source notify that they have been changed.
XAML is tricky!

Editable WPF ListBox

I have a ObservableCollection that's bound to a ListBox in WPF. I want the ListBox to be editable, and for the editing changes to be saved to the collection. Since WPF doesnt provide an editable listbox, I've tried creating my own by changing the ListBox.ItemTemplate.
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Name="EditableText" Text="{TemplateBinding Content}"/>
</DataTemplate>
</ListBox.ItemTemplate>
Changing the ItemTemplate gives me editable boxes, but any changes to the textboxes dont get saved to the ObservableCollection. Is there a way to have an editable ListBox with two way binding?
You cannot do it this way.
To achieve that kind of trick, you would need your items to be "holder classes" that expose a property you can bind your textbox to.
To understand it, imagine the following pseudo sequence of calls:
class ListBox
{
Bind(Items)
{
foreach(var item in Items)
{
DataTemplate Template = LoadTemplateForItem(item.GetType()); // this is where your template get loaded
Template.Bind(item); //this is where your template gets bound
}
}
}
Your template (the DataTemplate with the listbox) is loaded and the item (which I assume is a string in your case) gets passed in.
At this point, it only knows the string, and cannot influence anything upwards. A two-way binding cannot influence the collection because the template does not know in which context it is being used, so it cannot reach back to the original collection and modify its contents.
For that matter, this is the same thing for the TextBox. If it is not given a conainer and a property name, it has nowhere to "store back" the changes.
This basically the same as passing a string into a function call. The function cannot change which string was passed in (ignoring tricks such as by-reference argument passing).
To get back to your case, you need to build a collection of objects which expose a property containing the value that needs to be edited:
public class MyDataItem
{
string Data { get; set;}
}
Then you can bind your ListBox to a collection of those items and modifiy your datatemplate:
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Name="EditableText" Text="{Binding Data, Mode=TwoWay}"/>
</DataTemplate>
</ListBox.ItemTemplate>
Bind to a model property -- i.e. a property of the data object -- rather than to a view property such as Content. For example:
// model class
public class Widget : INotifyPropertyChanged
{
public string Description { ... }
}
<!-- view -->
<DataTemplate>
<TextBox Text="{Binding Description}" />
</DataTemplate>
Note this will not work if your ItemsSource is ObservableCollection (because there's no property to bind to).

Categories