Hi all,
I need to design a custom control based on the XamComboEditor which is capable of filtering the contained items in the following manner:
The control holds objects of type:
public class CodeData
{
public string Code { get; set; }
public string DisplayableLabel { get; set; }
public DateTime? ExpirationDate { get; set; }
public override string ToString()
return DisplayableLabel;
}
The value "code" is what interests me, however the control needs to display "displayableLabel".
The control needs to hold an exclusion list containing elements ("Code") that should never be displayed.
When a user opens the dropdown only those codes that are present in a databound collection minus the codes in the exclusion list should be displayed.
In code, however, it needs to be possible to assign a code that exists in the databound collection, regardless whether it is present in the exclusion list. When assigning in code it should appear as the selected item, and should be shown in the comboEditor, but not should not appear in the dropdown list. In this way, a user cannot set the ComboEditor to an excluded item, but in code, it can be.
As a small experiment, I wrote the following XAML. Here I try to have only the elements show that start with "a". This does not appear to work.
<ig:XamComboEditor x:Name="Cbx" AutoComplete="False" AllowFiltering="True" DisplayMemberPath="DisplayableLabel">
<ig:XamComboEditor.CustomItemsFilter>
<ig:ItemsFilter>
<ig:ItemsFilter.Conditions>
<ig:ComparisonCondition Operator="StartsWith" FilterValue="a"/>
</ig:ItemsFilter.Conditions>
</ig:ItemsFilter>
</ig:XamComboEditor.CustomItemsFilter>
</ig:XamComboEditor>
Code behind:
public InfrComboBoxCode()
InitializeComponent();
var code = new CodeData { Code = "aTEST", DisplayableLabel = "aTest code", ExpirationDate = null };
_collection.Add(code);
var code2 = new CodeData { Code = "bTEST2", DisplayableLabel = "bTest code2", ExpirationDate = null };
_collection.Add(code2);
var code3 = new CodeData { Code = "cTEST3", DisplayableLabel = "cTest code3", ExpirationDate = null };
_collection.Add(code3);
Cbx.ItemsSource = _collection;
What am I doing wrong? How should I implement the more complex filter criterium that abides by the exclusion list?
I've tried implementing my own IFilterCondition, but I have no clue on what the methods should be doing.
Many Thanks,
Hi
Thanks for sharing your solution and for the additional information. Please let me know if you have any other questions.
-Slavi
I have 'solved' the issue by first filtering the collection, then binding it to the control.
Then, I use the selectionChanged event to check whether the newly selected item is contained in the collection or not. If not, i add it to the collection.
Right after I bind selectedItem I fire this event.
In this way only items are included in the list that have passed the filter, or when they are selected in code (or through the databinding).
I agree that now the added 'excluded' item is present in the dropdown list and can be selected. When I would remove it from the collection before opening the dropdown, the selection would dissapear if I simply close the dropdown again without changing selection. Since the previously selected item is no longer in the collection.
I believe that i can leave the value in the list however, since a user can also cancel an edit-operation and the value would remain. So this topic can be marked solved.
The use case for this control is the following:
We have a database in which there are many lists of these kinds of codes. A code is a short string, accompanied by a description.
These lists of codes represent states, types, enums related to the business. Users of the application often need to change the state of some entity, but in some screens it does not make sense to show the entire list. The control I'm contructing here enables you too simply say which list you want to show using the properties pane, and which specific codes of this list should not be included.
A simple example;
If I retreive the file of some person in our application I would like to have the box show their 'gender' code (the description really) on the screen. However, this list contains male, female and unkown. Some other screens allow to edit someones file, here I would like to use the same control but only allow the user to change the gender to male or female. However, if the person happens to have 'unknown' in the database it must be shown.
There is more complexity to it. Codes also have expiration dates. Codes that are expired should also be filtered out and so on. Expiring a code in the database should therefore remove it from all these comboboxes in the application..
I realize that this probably isn't the most efficient way of creating this kind of functionality, but it's an enormous application with tons of legacy code...
Many thanks for all the help
Hi,
If the idea is to set selected item to a CodeData object that should not be in the drop down you could do this:
When in code you set the selected item to such object before you do that you can add it to the collection that the combo box is bind to. If the idea is the user to not be able to select such value from the UI you could handle the DropDownOpening and remove it like this:
private void btnSetSelectedItem_Click(object sender, RoutedEventArgs e)
_collection.Add(new CodeData { Code = "cTEST4", DisplayableLabel = "cTest code4", ExpirationDate = null });
Cbx.SelectedItem = _collection[3];// new CodeData { Code = "dfdf", DisplayableLabel = "dfdf", ExpirationDate = null };
private void Cbx_DropDownOpening(object sender, System.ComponentModel.CancelEventArgs e)
var cTEST4 = _collection.FirstOrDefault(i => i.Code == "cTEST4");
if (null != cTEST4)
_collection.Remove(cTEST4);
Please let me know if this works for you ? I am not sure what exactly is the user case you have in mind so if this is not helpful please provide a sample or more information regarding the scenario where the SelectedItem is set from code and what is expected the end user to be able to select.
Thanks,
Slavi
I need to complicate the requirements somewhat.
The selected item of the combobox is (two-way) databound as well.
When the bound item is something that does not appear in the filtered databound collection, won't this cause problems?
Many thanks,
your explanation is clear :)