I'm making a UserControl which uses a ListBox. In some moment I need to get the text of the selected item in the ListBox. The "normal" way I would go is:
var selected = (CustomObject)listBox.SelectedItem;
var str = selected.PropertyShowingInListBox;
But for some reasons of the UserControl I can't cast the SelectedItem. So my next chance is to get the text by reflection using the SelectedItem as object and DisplayMemberPath. Like this:
var selected = listBox.SelectedItem;
var str = selected.GetType().GetProperty(listBox.DisplayMemberPath).GetValue(selected, null).ToString();
But it isn't the best. Is there any way I use?
Related
I have worked with coded UI for web applications but for the first time I am trying to leverage Coded UI for WPF. I want to perform a click on an item from a combobox But, I am unable to achieve the same here in WPF. I tried to loop through the items inside the combo box but It did not work. Tried with Search Property - No result. Also, was trying to figure out the AutomationElement stuff but not able to get a solution. It would be great if I can get an idea of the approach that needs to be followed to achieve the requirement.
I have captured the controls and want to play around with them. No record and playback.
You can use the WpfComboBox's SelectedItem property which takes the name of the item you want to select (as mentioned in my comment in yonder answer)
var myComboBox = this.UIMap.UIMainWindowWindow.UIItemComboBox;
var items = myComboBox.Items;
myComboBox.SelectedItem = items[0].Name;
or you can simply set the SelectedIndex if you already know the index of the item you want to set
var myComboBox = this.UIMap.UIMainWindowWindow.UIItemComboBox;
var items = myComboBox.Items;
myComboBox.SelectedIndex = 0;
or you can first click the combobox to get it expanded and then get the UITestControl for the item element and perform a click on it (unfortunately you have to manually click the combobox because it seems that the ExpandWhileSearching configuration it doesn't work on it)
var myComboBox = this.UIMap.UIMainWindowWindow.UIItemComboBox;
var items = myComboBox.Items;
Mouse.Click(myComboBox);
Mouse.Click(items[0]);
or
var myComboBox = this.UIMap.UIMainWindowWindow.UIItemComboBox;
var items = myComboBox.Items;
myComboBox.Expanded = true;
Mouse.Click(items[0]);
You would create the combobox object the same way you would in Html, just using Microsoft.VisualStudio.TestTools.UITesting.WpfControls namespace. For example:
public WpfComboBox tester
{
get
{
WpfComboBox target = new WpfComboBox();
return target;
}
}
Then, you will create a UITestControlCollection object to store the .Items of the combo box.
UITestControlCollection comboBoxItems = tester.Items;
From here, you should be able to edit and set selected items ( tester.SelectedItem = comboBoxItems[0].ToString();) at will.
I have a DataGrid whose ItemsSource is set to a DataTable. The DataTable has a column of type DateTime, and I would like to display informational text (ie. "N/A") if the date in a particular cell is a certain value.
My first thought was to somehow bind the cell content to itself, and use a converter, but I can't seem to get it working correctly, and it seems as though there should be a better way.
Additionally, both the DataGrid and DataTable are dynamically generated, so this has to be done in the code behind.
Here's the code I tried initially:
// Create a new DataGridCellStyle
Style myStyle = new Style();
myStyle.TargetType = typeof(DataGridCell);
// Create the binding
Binding myBinding = new Binding();
myBinding.RelativeSource = RelativeSource.Self;
myBinding.Converter = new DateTimeToStringConverter();
// Add the Content setter
Setter mySetter = new Setter();
mySetter.Property = ContentProperty;
mySetter.Value = myBinding;
myStyle.Setters.Add(setter);
// Set the Style and ItemsSource
myDataGrid.CellStyle = myStyle ;
myDataGrid.ItemsSource = myDataTable.DefaultView;
DateTimeToStringConverter does implement IValueConverter, but I'm guessing the problem lies somewhere with the binding, since DateTimeToStringConverter is never actually called when the DataGrid is displayed.
At first, you Add the variable with the name setter to the Setters collection, but you are define the variable with the name mySetter. It may be a reason, why your Converter is not actually called.
Also the solution for your problem will be a bit more complicated.
Actually the Convert get a value of type RowDataView which contains a data for whole row. There is not an information in the converter about a Column or a Cell that is actually binded.
Better will be skip AutoGenerateColumns and generate them programmatically.
Here is example:
myDataGrid.ItemsSource = myDataTable.DefaultView;
myDataGrid.AutoGenerateColumns = false;
foreach (DataColumn column in myDataTable.Columns)
{
Binding binding = new Binding(column.ColumnName)
{
Converter = new DateTimeToStringConverter()
};
DataGridColumn gridColumn = new DataGridTextColumn
{
SortMemberPath = column.ColumnName,
Header = column.ColumnName,
Binding = binding
};
myDataGrid.Columns.Add(gridColumn);
}
Of course, for a performance will be better use the converter only in a DateTime columns.
I have a very basic question about Windows Forms datasources.
If I assign the same object data source to a combobox and a listbox on the same form I observe interesting UI behavior: when I change the item in a combobox (or listbox) the other control selects the same item.
I have no extra code for this UI behavior so I wonder how it works.
var persons = new List<Person>
{
new Person {Id = 1, Age = 10, Name = "Alex"},
new Person {Id = 2, Age = 12, Name = "Boris"},
};
// ListBox
lbPersons.DisplayMember = "Name";
lbPersons.DataSource = persons;
// ComboBox
cbPersons.DisplayMember = "Name";
cbPersons.DataSource = persons;
Please, explain how a control's selected item is changed synchronously?
I have found some similar problems on the web. I don't fully understand how this works, but I will give my best shot at it:
When you have a bind multiple controls to the same datasource, they use the same bindingcontext. Therefore, switching the selected item on one control will change the the selected item on the other control.
Instead when you bind the datasources, give each one a new BindingContext:
lbPersons.DisplayMember = "Name";
lbPersons.DataSource = persons;
lbPersons.BindingContext = new BindingContext();
cbPersons.DisplayMember = "Name";
cbPersons.DataSource = persons;
cbPersons.BindingContext = new BindingContext();
I found this info in a forum (link below) where they confirm the issue and have a solution. I need to do more reading on this, but more info can be found in the msdn at:
http://bytes.com/topic/c-sharp/answers/850851-multiple-controls-bound-same-data-source
http://msdn.microsoft.com/en-us/library/system.windows.forms.bindingcontext.aspx
EDIT as per:
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.bindingcontext(v=vs.71).aspx
The BindingContext object of a Control is used to return a single
BindingManagerBase object for all data-bound controls contained by the
Control. The BindingManagerBase object keeps all controls that are
bound to the same data source synchronized. For example, setting the
Position property of the BindingManagerBase specifies the item in the
underlying list that all data-bound controls point to.
Also:
(http://msdn.microsoft.com/en-us/library/system.windows.forms.bindingcontext.bindingcontext(v=vs.71).aspx)
For example, if you have two BindingManagerBase objects (from two
different BindingContext objects), you can set the Position properties
of each BindingManagerBase to different values causing each set of
data-bound controls will display different values from the same data
source.
I have a ListView which contains four column, In which i am adding items dynamically as :
ListViewItem lvi = new ListViewItem();
lvi.Background = ... color you want ... ;
lvi.Content = new {Server = "test1", .... };
listViewResult.Items.Add(lvi);
Now I want to sort this dynamically generated ListView on a perticular column click.
How can I achieve this?
I found article here which explain the custom sorting.
VirtualizingStackPanel.IsVirtualizing=”True”
First you need to specify the above property to true in your ListView, (this is the default value for ListView in WPF).
Then next, you need to use custom sorter, instead of SortDescriptions as described in my earlier blog. The key is using the CustomSort property of ListCollectionView:
ListCollectionView view = (ListCollectionView)CollectionViewSource.GetDefaultView(myListView.ItemsSource);
Then in your ColumnHeader click event handler, you add something like the following:
view.CustomSort = sorter;
myListView.Items.Refresh();
Where sorter is a custom class you implement the IComparer interface.
I'm trying to populate a ComboBox programatically. I am creating ComboBoxItems and would like to set their text (the text that is visible for the end-user) and their value (the object that I will handle in the background after the user has selected it.
However the ComboBoxItem seems to only have one member for these two requirements: the Content variable. At the same time this would not fit my needs as I want to distinguish the text and value properties and want to do this without data binding. Is there some viable solution to achieve this?
My current code looks as follows:
ComboBox comboBox;
ComboBoxItem item = new ComboBoxItem();
item.Content = "First Item";
item.Value = 1; // Does not work, no such member as Value!
comboBox.Items.Add(item);
Guess you can use the Tag property.