I'm looking to create a WPF textbox control that acts similar to the email recipient textboxes in Outlook (the To, Cc and Bcc inputs). I don't necessarily care that much about auto-completion (i've found millions of examples for that), but what I'm really struggling with is how to have delimited text entries in the textbox behave as entities the way they do in Outlook (once a recipient you've entered resolves, that text becomes an 'entity' which you can click to select, right click to get a context menu, etc. it's not longer 'plain text' in which you can place your cursor)...
Does anyone have any high level ideas how to accomplish this? Know of any existing examples (I've googled for hours)?
Thanks so much in advance,
Michael.
My rough thought process would be this... (note: I'm not actually coding it, so my details may be a little off...).
High level behaviour:
the type of data in your control is a list of items which aren't selectable. Therefore your control is, approximately, an ItemsControl (in terms of visual/XAML, it's an ItemsControl with a WrapPanel style layout and very simple TextBlock for the item template).
when your control gains focus, you need to switch the template to be a TextBox
when your control loses focus, you need to split the inputted text and convert it to a list for display.
Therefore, thinking code:
you need a UserControl, possibly derived from ItemsControl. That gives you basic behaviour to represent a list of items.
you need a custom DependencyProperty on your control that represents the delimited string.
when the string property changes, you need to parse it and replace the list of items in the control.
when the list property changes, you need to replace the string property with a suitably-delimited list.
In terms of code-behind, that part should be pretty simple. Then, for the XAML template...
you need a base template that displays your Items property as a list, using the WrapPanel layout mentioned above.
you need a trigger that replaces this template when the control has focus.
the replacement template should be a TextBox that is bound to the string property of the control.
the default binding behaviour on a TextBox will only push a new value when the TextBox loses focus, so you need to think about whether you want to make, say, an "Enter" keypress move focus (thus reverting the template to the list version - when the string property's value changes, your codebehind will update the list).
This should give you the basic behaviour. You should be able to bind either the list property or the string property from outside of the control, though you may have to be careful about what happens if you bind both properties since there's a two-way dependency between them...
Related
Background:
I use converters to acquire values for most of my binding statement because the bindings are so complicated that even multi-binding cannot satisfy. I have to calculate the value in the converters and return the value. Also I use OneWay or OneTime binding just to show the correct value. When user changes a value, I use Handlers to set the value. The Handlers are also complex program which cannot be simply replaced by TwoWay or OneWayToSource binding. Actually in this case the DataContext does not have any meaning. I use converters. Another reason of using converters is that all Controls are loaded dynamically using many DataTemplates and it's hard to create dynamic DataContext for each Controls in each DataTemplate.
With above background, my application works fine. I'm looking for solutions for our new problem below.
I have many group of Buttons each represent a warehouse containing different type of items.
When double-click a Button, a detail window pops up and user can modify the items. Those items can be represented by CheckBox, Combobox, TextBlocks, TextBox, etc.
For user's convenience, I duplicated some of the frequently-modified Controls from the popup window onto the Button itself (WPF allows Button to contain sub-controls), so that user can directly modify the items without double-click and popup the detail window.
Each Button could contain unknown number of sub-controls such as CheckBox, Combobox, TextBlocks, etc. Here "unknown" means that in the future developer can duplicate any controls onto the Button if the Controls for those items are deemed frequently-modified.
Everything works fine so far.
When user modifies an item in the popup window and closes the window, I used to reload the DataTemplate for the whole window so that everything is refreshed and the controls duplicated onto the Button can synch up with the value modified from inside the popup window.
Everything still works fine so far.
The problem happens when the application runs on machine with slow hardware, where performance is an issue. On a much slower machine, reloading the whole DataTemplate for the whole application that contains many Buttons is quite slow.
So I'm looking for ways to just refresh the Button that is double-clicked, not all Buttons. However, I searched a couple of days and could not find ideal solution of refreshing a WPF sub-tree.
I tried to travel the sub-tree of the Button to assign null to the DataContext property and then assign back the old DataContext, but the binding seems not triggered and the converters were not called.
I saw someone suggested to use something like below:
((ComboBox)sender).GetBindingExpression(ComboBox.ItemsSourceProperty)
.UpdateTarget();
That demands that I know the Control and its property that has bindings. I think I can do the same for all possible Controls and properties but it does not seem a future-proof solution.
Anybody knows an effective way of refreshing a WPF sub-tree without knowing what is in the sub-tree?
I have a Silverlight 3 control where I am using an ItemsControl to display a list of items. I have implemented a "filter" or "search" textbox that allows the user to enter a search term in a textbox on the control that will limit the items displayed in the ItemsControl to ones that contain the string entered in the textbox. I have been able to implement this functionality, but I'd like to enhance it by changing the color of the text of the search term in the text that is displayed in the items control. For example, if the user types "foo" in the search textbox, I would like to filter the items in the ItemsControl (which I am already doing) to items that contain "foo", and change the background color of the substring "foo" where it occurs in the ItemsControl.
Ideally, I would implement an IValueConverter and pass the value in the search textbox as the parameter to the converter. The converter could then search through the value that is being converted and change the background color of all "foo" substrings (not sure how I'm going to do this yet, something with Inlines maybe?). It seems parameter values passed to value converters must be static resources. Is there any way I can pass a non-static value to the value converter to accomplish what I'm trying to do? Is there another way I should be going about this that does not use an IValueConverter?
Mind you I haven't worked this out completely yet, but I do something sort of similar in my app using Interaction.Behaviors. This is a little more flexible than a straight converter solution. In my solution, I use it to highlight cells and/or text in a grid based on various conditions (e.g. is this a critical item? Make it red).
Take a look at this blog entry, it explains the process fairly well, and should apply to more than just a Telerik RadGridView. (FYI, I think you'll need to add a reference to System.Windows.Interactivity)
Blog
I'm trying to achive displaying the RowDetailsTemplate of a Silverlight DataGrid depending on a bool Property, bound to a CheckBox Control's IsChecked Property. Insinde of my RowDetailsTemplate there is a single custom UserControl, containing further Controls.
Since the DataGrid only allows a global setting (RowDetailsVisibilityMode) Some code-behind is needed. I've implemented a solution based on Rorys Reply (and using a behaviour-technique) which actually works.
Unfortunately, The DataGrid doesn't remember the individually shown or hidden Rows on sorting. The checkbox remains selected, but the Row collapses. Further, no event like "OnAfterSort" or something similar seems to exist, where i could "Refresh" the visibility settings in a loop.
Another idea was to bind the Visibility of my custom Details-UserControl to the CheckBox bound value. This actually works (when settings RowDetailsVisibilityMode to "Visible"), but I'm not able to get rid of this weird behaviour: When the CheckBox is checked, the Detail Template expands and the detail UserControl appears. Nice. When the CheckBox is unchecked again, the UserControl disappears (Visibility is set to Collapsed) but the Row doesn't collapse and the blank space remains (as it would be set to Hidden not Collapsed).
Do you have any ideas?
I hope it's ok I didn't post any code samples, the implementation is pretty easy and I believe that the problem doesn't actually lie in a coding mistake i made. You can setup a simple DataGrid quickly like in this perfect MSDN Example. Starting from here, it's easy to test both described behaviours!
Really big thanks in advance,
- Thomas
I've got a list of things that I want the user to easily edit the order of. Right now I'm binding them to a ListBox with a custom ItemTemplate. Within that template I have an UP & DOWN button. My goal was to move the item up/down based on the button clicked.
However I'm having trouble associating the button's click event with the actual item in the list. I've seen some folks setup a drag/drop for ordering items but that that would be too complex for this app (it's target user base =1, just me).
I assume this is possible with a ListBox. Maybe someone has a beter idea on how to implement this? It's not a huge set of data... less than 25 items.
The DataContext of the button (of the entire template, thus inherited by the button) is the item itself. Simply cast it to your desired type.
I've got a Combo Box that is databound to an ObservableCollection of items. I would like to have a default selected item that is (None) that would set the value of the property I've bound to "SelectedValue" to null.
I think there ought to be a way to achieve this with some combination of Style/DataTemplate/TemplateSelector. I'm trying to design this with MVVM in mind, so I'd like something that doesn't use codebehind and is as reusable as possible. I'd also like the benefits of the ObservableCollection (updating the collection causing the control to rebind) to remain intact.
Bonus part B:
I would like to also be able to append an extra visual element to the bottom of an ItemsControl as well. I was thinking it would be easy to change the DataTemplate if I knew how to trigger it on the last item of a collection. Willing to entertain other options here.
The simplest way I've found to do this is to insert a "special" value into the underlying collection, and display the "(None)" text when it's selected. Obviously then you need to run your binding through a converter to take this value into account and return null when it's selected. (See this question of mine which was a result of me trying to add an actual null value to a ComboBox's underlying collection.)
Having said that, it might actually be possible to do what you want with the CompositeCollection class. You could make a separate collection (with only one item - your Null item) and bind your ComboBox to both it and your original collection through the CompositeCollection.