how to bind autocomplete box to a database table column? - silverlight

i am currently creating a Gridview using telerik control which displays data from the sql database which i displays through domain datasource used in wcf ria.(ADO.net entity model etc)
i want to add an autocomplete box above my radgrid where i type an name and other matchable entries are also listed.
when i click on the entry then radgrid may display whole row containing that name.
i am using silverlight 4,wcf ria,telerik controls.
please provide a sample coding idea in xaml and xaml.cs.
i tries to access telerik demos but they are not running on my system.

As an example... say you have a list of Customers, of which you want to display their names in your AutoComplete box. Further, your Grid should display all customers, and when a Name is selected in the AutoComplete box, the Selected item of the grid displays.
What you need to do is bind the SelectedItem property of the RadGridView & AutoCompleteBox. What I would do is bind the AutoCompleteBox to a property named SelectedName, like so:
<input:AutoCompleteBox ItemsSource="{Binding Names}" SelectedItem="{Binding SelectedName, Mode=TwoWay}" />
Emphasis on the 'Mode=TwoWay' - this is what will alert your code behind that the UI has changed.
In your code behind, you would create properties like this:
private string selectedName;
public string SelectedName
{
get { return selectedName; }
set
{
if (value != null)
{
var query = (from c in CustomersList
where (c.Name == value)
select c).FirstOrDefault();
SelectedCustomer = (Customer)query;
selectedName = value;
}
}
}
Notice how, when you're setting the SelectedName, you're using LINQ to determine which of the customers were selected. One pitfall here would be if you have multiple names in a list... this code only selects the first. If this is an issue, you probably should rethink your architecture..
Then for your grid, you would bind the SelectedItem like so:
<telerik:RadGridView
....
SelectedItem={Binding SelectedCustomer, Mode=TwoWay"}
....
</telerik:RadGridView>
In your code behind, you'd create this property:
private Customers selectedCustomer;
public Customers SelectedCustomer
{
get { return selectedCustomer; }
set {
selectedCustomer = value;
MyGridView.SelectedItem = selectedCustomer;
}
}
Something like that should get you started.
SS

Related

WPF MVVM Listview itemsource binding with list in a class property

I have a page with two parts :
A Listview with itemsource binded with a class, ObservableCollection "Patients" loaded with "Patient" class.
Under the Listview are Textboxes binded with the selecteditem Patient. Everything works without writing any code in the page, except in selection_changed to scroll to selected item.
A second Listview must display the details "Visites" from the selected "Patient".
The application works in a MVVM Framework with a Viewmodel containing the properties for the page.
The problem is to make the relation between the two ListView. I tried first building the second list "Visites" in the NotifyPropertyChanged event :
if (Patient.ID > 0)
{
LoadVisite(Patient.ID); // fill the details list "Visites"
NotifyPropertyChanged("Visites");
}
No delail is shown when "Patient" is selected.
I tried another solution inserting the list of details in the master class "Patient like this :
public Class Patient
...
public ObservableCollection<ClsVisite> Visites
{
get
{
return _visites;
}
set
{
_visites = value;
}
}
// WDABase class to open the database and load data connection
WDABase wd = new WDABase();
wd.LoadListeVisites(ID, _visites); //ID is the relation beween the two tables
}
}
Now I try to create the Listview detail itemsource in the XAML like this :
<ListView Name="ListeVisites" ItemsSource="{Binding Path=Patient.Visites}" SelectedItem="{Binding Visite}">
No details where shown.
The unique solution I found was to add some code in the selection_changed event of the master Listview like this (in this case the listviews are in two different frame) :
private void ListePatients_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
ListePatients.ScrollIntoView(ListePatients.SelectedItem);
if(ListePatients.SelectedItem != null)
{
var w1 = ((System.Windows.FrameworkElement)App.Current.MainWindow.Content).Parent;
Frame pageVisite = (w1 as MainWindow).Visit;
var w2 = (System.Windows.FrameworkElement)pageVisite.Content;
ListView Lv = (w2 as Visite).ListeVisites;
Lv.ItemsSource = (ListePatients.SelectedItem as ClsPatient).Visites;
}
}
And it's works but is there another elegant solution to bind the itemsource of the details Listview ?
Thanks for helping me.
Jean-Marie
I found the solution to my problem.
The Reason the details were not displayed is because the frame used for the listview is not common with the master frame.
I discover that when I display the details frame the "Patient" object contains only null. I Don't know why but I read about sharing ViewModel and now I use a common one in App.xaml and I Don't need to specify the itemsource for the details Listview in code. I put in XAML itemsource={Binding Patient.Visites} and everything works.

How to get the value from DataGrid's SelectedItem?

In my project i have one Datagrid and i bind the following fields that are listed below.
CustomerID, Name, Email.
I have the Entity named WS_Customer. i have put one button control for all row in datagrid.If i click the button means the i need to get the CustomerID value.
How to get it.
If i put like this means,
WS_Customer getid=(WS_Customer)DG.SelectedItem;
getidshows null..
How i got the value?
Assuming you are using MVVM... and you DataGrid is bound to a collection of the WS_Customer objects you can put a property in your view model that you can bind to the SelectedItem property of the DataGrid. Keep in mind the row must be selected for the SelectedItem property to have a value.
In xaml:
<DataGrid SelectedItem="{Binding SelectedWS_Customer}" />
In viewModel:
public WS_Customer SelectedWS_Customer
{
get
{
return _selectedWS_Customer; //private variable
}
set
{
_selectedWS_Customer = value;
}
}

MVVM WPF databound checkbox won't firing events to the ViewModel for Checked and Unchecked states

I have a databound CheckBox inside a DataGrid, using WPF and MVVM;
<DataGridTemplateColumn Width="80" Header="Enabled">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Path=IsEnabled, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Name="theCheckbox" HorizontalAlignment="Center"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
This works fine and the CheckBox is being checked when IsEnabled is set. IsEnabled is a property in my collection of objects which I have bound to the DataGrid. What I want to do is to be able to validate if a specific rows CheckBox within the DataGrid should be allowed to be checked when the user selects it and if not remove their check and display a warning message something like "Row 1 cannot be checked without rows 5 and 9 being checked". I found out how to do this using code behind using the Checked and Unchecked properties of the CheckBox, but I am using MVVM and therefore want to handle things in the ViewModel associated with the View the DataGrid and CheckBox are in. How do I do this? I need a way of passing the Id field of the DataRow through too in order to identify which row I am working on, for arguments sake lets say the Id field is called BorderId.
Implement IDataErrorInfo on your objects, which is WPF's default interface for validation, and setup your validation code to validate if the checkbox can be checked or not
This is actually a bit trickier than normal because you are validating a property on your data item using data that doesn't exist on the data item, which means you need to provide some way of attaching unrelated validation to your object at run time.
The solution I usually use is to expose a ValidationDelegate from my object, which other objects can use to attach additional validation to the object. The code for it is posted on my blog, and it allows you to attach validation to your object like this:
public class MyViewModel
{
// Keeping this generic to reduce code here, but it
// should be a full property with PropertyChange notification
public ObservableCollection<SomeObject> SomeCollection { get; set; }
public MyViewModel()
{
SomeCollection = LoadDataGridObjects();
// Add the validation delegate to each object
foreach(var item in SomeCollection)
item.AddValidationDelegate(ValidateObject);
}
// Validation Delegate to verify the right checkboxes are checked
private string ValidateObject(object sender, string propertyName)
{
if (propertyName == "IsChecked")
{
var item = (SomeObject)sender;
if (item.Id == 1
&& !SomeCollection.First(p => p.Id == 5).IsChecked
&& !SomeCollection.First(p => p.Id == 9).IsChecked)
{
return "Row 1 cannot be checked without rows 5 and 9 being checked";
}
}
return null;
}
}
Could you add to the PropertyChanged event handler of each item in your list? Something like this:
foreach (Object x in List)
{
x.PropertyChanged += OnItemChanged;
}
Then in the change listener you can do whatever you like with the sender object including changing the IsEnabled property.
void OnItemChanged(object sender, PropertyChangedEventArgs e)
{
// change sender object properties or set bound label text here
}
If I understand your question, you have a checkbox and you want to control if it can be checked or not. Instead of letting the user check it at all times and push back an error message if you don't want to allow it, make your checkbox inactive in the first place if you don't want the user to check it.
To do this through your ViewModel (which is of course your DataContext), you need to bind the Checkbox's "Command" to a custom command in your ViewModel.
A WPF Command will provide the following functionality:
Automatically enable/disable a control based on custom logic
Handles the "action" event of your control (on a button of checkbox, it would be "click").

Data binding a WPF ComboBox from a ViewModel - can't change selected item

I'll get this out of the way right off the bat... my base view model class is implementing INotifyPropertyChanged. Here's the scenario:
I have a single view with a single view model. The view is a master/detail with the master being a list box of Game objects that I'm populating without issue. When a Game object is selected in the master list box, I want to populate some details in various controls. The control that's causing me problems is a combo box.
Now, the combobox is being populated using a collection of Team objects. Each Game object has a "Team" object and once the combobox is populated, I want to select the appropriate Team object in the combobox that the Game object specifies.
Now, I know this is working to some degree because if I do the same binding to a textbox, the right information appears (I can get the bound Team object to appear in the textbox, but I can't get it to select from the list).
I'm seriously lost, been working on this for a few hours now. Can anyone assist?
Edit: I have a feeling this has something to do with the object references. But wouldn't SelectedValue still work?
ViewModel:
public ObservableCollection<Team> Teams
{
get { return this.teams; }
set
{
this.teams = value;
OnPorpertyChanged("Teams");
}
}
public Team SelectedTeam
{
get { return this.selectedTeam; }
set
{
this.selectedTeam = value;
OnPorpertyChanged("SelectedTeam");
}
}
private ObservableCollection<Team> teams;
private Team selectedTeam;
Team Class:
public class Team
{
public string Name { get; set; }
}
View:
<ComboBox DisplayMemberPath="Name"
ItemsSource="{Binding Teams}"
SelectedItem="{Binding Mode=OneWayToSource, Path=SelectedTeam}" />

WPF ComboBox which updates its ItemsSource from the database as the Text property changes

I would like to have a ComboBox control on a form which will be used to search a list of investments as the user types. I can do this easily if I cache the entire collection of investments from the database on startup (currently 3,000 or so items), but I would prefer to not do that if it isn't necessary.
The behavior that I am trying to implement is:
The user types text into the editable ComboBox.
As the user enters each character, the database search function is triggered, narrowing down the search results with each successive keystroke.
As the search results are updated, the dropdown panel opens and displays the relevant matches
I have tried binding the Text property of the ComboBox to the InvestmentName (string) property on my ViewModel, and the ItemsSource property of the ComboBox to the InvestmentList (generic List) property on my ViewModel. When I do this, the Text property auto-completes from the ItemsSource, however the dropdown appears empty.
I have been able to achieve these results using a TextBox stacked on top of a ListBox, but it isn't very elegant and it takes up more screen real estate. I've also been able to get it to work with a TextBox stacked on top of a ComboBox, although the ComboBox steals the focus when the IsDropDownOpen property is set to "true" when there are valid search items. It also isn't very visually pleasing to use two controls for this.
I feel like I'm really close to getting it to work the way I want it to, but there is something which eludes me.
The XAML for this control is:
<ComboBox Height="23" Width="260" IsSynchronizedWithCurrentItem="True" HorizontalAlignment="Left"
ItemsSource="{Binding InvestmentList}" DisplayMemberPath="FullName"
IsDropDownOpen="{Binding DoShowInvestmentList}"
ItemsPanel="{DynamicResource ItemsTemplate}" IsEditable="True"
Text="{Binding Path=InvestmentName, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
The relevant ViewModel properties are:
private bool _doShowInvestmentList;
public bool DoShowInvestmentList
{
get { return _doShowInvestmentList; }
set { if (_doShowInvestmentList != value) { _doShowInvestmentList = value; RaisePropertyChanged("DoShowInvestmentList"); } }
}
private List<PFInvestment> _investmentList;
public List<PFInvestment> InvestmentList
{
get { return _investmentList; }
set { if (_investmentList != value) { _investmentList = value; RaisePropertyChanged("InvestmentList"); } }
}
private string _investmentName;
public string InvestmentName
{
get { return _investmentName; }
set
{
if (_investmentName != value)
{
_investmentName = value;
this.InvestmentList = DataAccess.SearchInvestmentsByName(value).ToList();
if (this.InvestmentList != null && this.InvestmentList.Count > 0)
this.DoShowInvestmentList = true;
else
this.DoShowInvestmentList = false;
RaisePropertyChanged("InvestmentName");
}
}
}
I've done a fair bit of research on this, but I haven't quite found the answer yet.
Check out this great article on CodeProject by... me :)
A Reusable WPF Autocomplete TextBox
Look towards the end for the Google suggest example, it is similar to what you need, where every keypress triggers another query to the server.

Resources