Can i create SelectedItems Property for multiselect combobox - c#

Currently I am working on multiselect combobox custom control with combobox inherited, which attached a listbox to a combobox with a multiple selection mode. But now I face a problem when passing the selected items to my custom control in view. I use the listbox selectionchanged event to update my selected item in my combobox. I'm able to implement this approach on selecteditem, it manages to pass one selected item to my view. But I want to pass all the selecteditems to my view.
And this is what I have done so far.
MultiSelectCombobox.xaml <-- My custom control xaml inherited from combobox
<ComboBox.Template>
...
<Popup>
<ListBox SelectionMode="Multiple" ItemsSource="{TemplateBinding ItemsSource}"
SelectionChanged="ListBox_SelectionChanged">
...
</ListBox>
</Popup>
MultiSelectCombobox.xaml.cs
public partial class MultiSelectComboBox : ComboBox
...
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBox lb = sender as ListBox;
this.SelectedItem = lb.SelectedItem;
}
MainWindow.xaml.cs
MultiComboBox mComboBox = (sender as MultiComboBox);
MessageBox.Show(this, mComboBox.SelectedItem.ToString());
use this 2 line in some combobox event to display selecteditem.
I search through few posts, but I'm still unable to find any solution, I would appreciate if you could provide some guidance for me.

Try this...
MultiSelectCombobox.xaml.cs
public partial class MultiSelectComboBox : ComboBox
{
...
public static readonly DependencyProperty SelectedItemsProperty =
DependencyProperty.Register("SelectedItems", typeof(IList),
typeof(MultiSelectComboBox));
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBox lb = sender as ListBox;
this.SelectedItem = lb.SelectedItem;
this.SelectedItems = lb.SelectedItems;
}
}
Keep in mind that this would only work for one way selection. If you want to make sure it is only used to get the selected items and that nobody tries to set them this way, you could turn the DependencyProperty into a readonly one and use an IEnumerable instead of an IList.
If you wanna support two way selection changes (changing the selected items from code and not only from user interaction with the ListBox) then you'd have to add a property changed callback to the DependencyProperty and maybe use an ObservableCollection to listen for changes in the collection, and update the ListBox selection accordingly.

Related

SelectionChangedCommited functionality in Combobox (XAML)

In the example below, when i try to set values to the combobox, the event is triggered and change objRunSettings.xxx before the value is set to cmbxxx.SelectedValue.
I suppose i need something like SelectionChangedCommited instead of SelectionChanged but i am really confused how to do it, as in xaml my only option is SelectionChanged
In xaml
<ComboBox SelectionChanged ="cmbxxx_selectionChanged"/>
In .cs -> set combobox values
cmbxxx.SelectedValue = objRunSettings.xxx;
Event
private void cmbxxx_selectionChanged(object sender, SelectionChangedEventArgs e)
{
objRunSettings.xxx = cmbxxx.SelectedValue.ToString();
}
The first item in the e.AddedItems IList will be the value you are looking for.
MSDN SelectionChangedEventArgs

WPF ListBox, when selecting several items, why is the first item in the multi item selection omitted?

Hi I have a ListBox and set it up as follows in xaml:
<dxdo:LayoutPanel Caption="Raw Data File Names" ItemWidth="2*">
<ListBox ItemsSource="{Binding FilteredFileNames}" SelectionMode="Extended" SelectionChanged="Selector_OnSelectionChanged"/>
</dxdo:LayoutPanel>
When I handle the event in code-behind each time I select multiple items (via shift-down plus mouse click) I noticed that the first item is never included in the array of items:
private void Selector_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var vm = DataContext as HistoricalDataImportRawDataViewModel;
vm.SelectedFileNames = e.AddedItems.Cast<string>().ToList();
}
What am I doing wrong? Is it because AddedItems only include the items beyond the initial selection? What can I do to get the complete collection of items? Please note that I have to use SelectionMode="Extended". Is the omission of the first item intended or a bug?
The AddedItems property tells which item was added to the selected items. If you are interested about all the items that are selected, you have to access ListBox property SelectedItems.
var listbox = (ListBox) sender;
var selectedItems = listbox.SelectedItems
.Cast<string>()
.ToList();

Add items to ComboBox at runtime?

I am trying to add items to a ComboBox (say Name="labelComboBox") at runtime when I pressed an add button (say with Name="add2labels" Click="add2labels_Click"). But the ComboBox cannot show the values I newly added. What did I miss?
The following is the event handler for the add button:
private List<String> labels = new List<String>();
... ...
private void add2labels_Click(object sender, RoutedEventArgs e)
{
labels.Add("new value");
labelComboBox.ItemsSource = labels;
}
P.S. I am pretty sure the values were added to List<String> labels correctly (its count did increase each time).
Updated with workable solutions (3 ways) :
Use ObservableCollection (#AnatoliyNikolaev's answer).
Change List<String> labels to ObservableCollection<String> labels. And only need to call labelComboBox.ItemsSource = labels; once in all.
Use Binding (#HarshanaNarangoda's answer).
Add ItemsSource="{Binding Path=labels}" to ComboBox's properties.
Use Refresh() (#EliranPe'er's anwer).
Change the event handler to:
... ...
labelComboBox.ItemsSource = labels;
labelComboBox.Items.Refresh(); // new added
You should use ObservableCollection<T> instead of List<String>:
ObservableCollection represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.
Try using labelComboBox.Items.Refresh();
Combobox has a display and value member to add values to combo-box you need to specify both.
try this
ComboboxItem item = new ComboboxItem();
item.Text = "new value";
item.Value = 12;
labels.Items.Add(item);
I think You have to change some code in XAML to following.You have to bind data to your Combo Box.
<ComboBox ItemsSource="{Binding}" Height="23" HorizontalAlignment="Left" Name="comboBox1" />

get the clicked item from a IsItemClickEnabled ListView in C# and WinRT

how can I get the clicket elevent from a ListView which has the IsItemClickEnabled enabled?
I know how to get the selected Item/Index but not the clicked item.
ItemClick is working but I can not say s.th. like:
Object selection = listView1.SelectedItem;
EDIT:
I have a ListView and I need to catch the clicked item from this list in the following method:
private void listView1_ItemClick(object sender, ItemClickEventArgs e)
{
...
}
I may be missing something, but doesn't the following work for you?
private void lv_ItemClick_1(object sender, ItemClickEventArgs e)
{
var item = e.ClickedItem as String;
}
Here I assume the items in the list are simple strings, but in general they'll be whatever type you are using in the collection you've bound to the ItemsSource property of the ListView.
I guess you can also try the SelectionChanged event, and get the clicked item as e.AddedItems or MyListView.SelectedItem or MyListView.SelectedItems.

DataGridViewCombBoxColumn cell value and different dropdown list

I've a very trivial requirement which makes me go nuts. I've a DataGridView in windows forms application. This contains one databound ComboBox Column. I'm using DisplayMember and ValueMember properties of that combobox.
Now my requirement is ComboBox should show the list of DisplayMembers in drop down list but when user selects one item from it, I should display the part of that DisplayMember in the combobox cell visible to the user. For example.
My display member list looks as below:
"Cust1 - Customer 1"
"Cust2 - Customer 2"
"Cust3 - Customer 3"
and when user selects any one of them from the above list (Say user selected 'Cust2 - Customer 2') then I need to display the value in the combobox column cell as only "Cust2" instead of complete DisplayMember text.
This DisplayMember list is a combination of two fields from the datasource bound to it i.e. First part points to CustomerCode field and second part points Customer name. I need to display only CustomerCode in the ComboBox cell after user selects one item from the drop down list.
How can I do this? Or should I come up with my own control which will have a different AutoCompleteCustomSource and display member value. Even I'm confused with that approach too.
Update: As no one has come up with any solution to my problem. Now I'm starting a bounty for that, also if anyone can suggest me other way to implement the same functionality, it would be great.
I've even tried to come up with my own control and tried to work on simple combobox to display a different value than the selected dropdown list, even that didn't work. Is there any other way to implement this? Any tips and tricks are greatly appreciable.
#Anurag: Here is the code which I've used.
Created a datagridview in the design mode. Created one column of type 'DataGridViewComboBoxColumn' that and named it as CustomerColumn.
In the designer file it looks like below:
private System.Windows.Forms.DataGridViewComboBoxColumn CustomerColumn;
This is the entity class which I've used for datasource
public class Customer
{
public int Id { get; set; }
public string CustCode { get; set; }
public string CustName { get; set; }
public string NameWithCode { get; set; }// CustCode - CustName format
}
In the form load event I'm doing the following:
CustomerColumn.DataSource = GetCustomers();
CustomerColumn.DisplayMember = "NameWithCode";
CustomerColumn.ValueMember = "Id";
I'm answering my own question because I've implemented my own solution to this by using custom control.
This custom control is created by keeping a textbox above combo box in such a way that only drop down button of combobox is visible.
Now I've created a custom column in datagridview deriving the DataGridViewEditingControl from my usercontrol.
I've added a property in Usercontrol which will take drop down list source from the control which is hosting datagridview.
Now in the EditingControlShowing event I'm setting this property as below
private void dataGridView2_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if(dataGridView2.CurrentCell.ColumnIndex.Equals(0) && e.Control is UserControl1)
{
var uscontrol = e.Control as UserControl1;
uscontrol.DropDownListSource = source;
}
}
This drop down list source is used in the usercontrol to set the autocompletesource to the textbox and datasource to the combobox as below:
Whenever I set the DropDownDataSource I'm firing an event in the usercontrol which will do the following. This is to ensure that every time EditingControlShowing event occurs for this column in DataGridView, this source is updated for textbox and combobox in usercontrol.
private void DropDownSourceChanged(object sender, EventArgs eventArgs)
{
textBox1.AutoCompleteCustomSource = DropDownListSource;
textBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource;
comboBox1.DataSource = DropDownListSource;
}
Now whenever user starts typing in the textbox autocomplete source will display dropdown list with 'NameWithCode' values and if user selects one of them then I'll set it to the Text propery overidden in my usercontrol which will be used for the cell value in the DataGridView. Now based on the Textbox text (which is NameWithCode) I can get the code part and set it to the text property.
If user uses combobox dropdown button to select the item then I'll get the combobox selected text and set it in the Textbox which is ultimately used by the cell for getting value.
This way I could achieve the solution I want.
#Homam, solution also works but when I change the ComboBox's DropDownStyle to allow the user to type the value in the combobox it behaves weirdly and not getting up to the mark solution for my requirement. Hence I used this solution.
I know that this is not perfect solution, but I looked for a better one and I didn't find, so I went to a workaround
I did the following:
when the user open the ComboBox, I change the DisplayMember to "NameWithCode"
when the user close it, I return it to "CustCode"
You can Access to the ComboBox control by DataGridView.EditingControlShowing event for the DataGridView.
The code:
private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
{
var comboBox = e.Control as ComboBox;
comboBox.DropDown += (s1, e1) => comboBox.DisplayMember = "NameWithCode";
comboBox.DropDownClosed += (s2, e2) =>
{
// save the last selected item to return it after
// reassign the Display Member
var selectedItem = comboBox.SelectedItem;
comboBox.DisplayMember = "CustCode";
comboBox.SelectedItem = selectedItem;
};
}
Note: You have to start the DisplayMember with "CustCode"
Good luck!
Each time at the offensive of event dataGridView1_EditingControlShowing there is addition of new handlers for events comboBox.DropDown and comboBox.DropDownClosed. It results in the increase of number of these handlers and their repeated calls. This code decides this problem.
private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
{
var comboBox = e.Control as ComboBox;
comboBox.DropDown += comboBox_DropDown;
comboBox.DropDownClosed += comboBox_DropDownClosed;
}
private void comboBox_DropDown(object sender, System.EventArgs e)
{
var comboBox = sender as ComboBox;
if(comboBox != null)
{
comboBox.DropDown -= comboBox_DropDown;
comboBox.DisplayMember = "NameWithCode";
}
}
private void comboBox_DropDownClosed(object sender, System.EventArgs e)
{
var comboBox = sender as ComboBox;
if(comboBox != null)
{
comboBox.DropDownClosed -= comboBox_DropDownClosed;
var selectedItem = comboBox.SelectedItem;
comboBox.DisplayMember = "CustCode";
comboBox.SelectedItem = selectedItem;
}
}

Categories

Resources