Set VisualState of combobox when a item is selected in Xaml (Silverlight) - silverlight

When my combobox expands and I select an item, I want the combobox to change visual state(it is highlighted). This will signify something is selected. I tried various VisualStates but none of them would trigger in this scenario. How can I achieve this? Thanks.

The standard ComboBox simply doesn't have states to distinguish between having something selected and having nothing selected.
There are a number of ways to go about solving the underlying problem, and it depends mostly on the answer to the following question:
Do you really need to change the visual appearance of the ComboBox itself or does it suffice to style the selected item more prominently?
If it's the latter, you're best served with the rather easy way of using a custom control template for the ComboBoxItems.
If you really want to style the ComboBox itself that way, there are two options I can think of:
A) Add custom states to a ComboBox with a custom template.
Copy your ComboBox's control template and add another state group to the already present states. Both of this is typically done in Expression Blend.
After that you can update the new states in code with
VisualStateManager.GoToState(this, "Selected", true);
for example. You will have to set those states yourself when the first item is chosen. This could be done on the SelectionChanged event.
B) Derive from ComboBox
If you want to use the control in this way often, it might be worthwhile to derive from ComboBox to make your own custom control.
It would look somthing like this:
[TemplateVisualState(Name = "SelectedStates", GroupName = "Unselected")]
[TemplateVisualState(Name = "SelectedStates", GroupName = "Selected")]
// ... (more attributes copied from the ComboBox ones)
public class MyComboBox : ComboBox
{
public MyComboBox()
{
SelectionChanged += HandleSelectionChanged;
DefaultStyleKey = typeof(MyComboBox);
}
void HandleSelectionChanged(object sender, SelectionChangedEventArgs e)
{
VisualStateManager.GoToState(this, SelectedItem != null ? "Selected" : "Unselected", true);
}
}
And you would then need a default style based on the default ComboBox style (or whatever you usually use).
Note that I didn't test this in any way.

Related

Commands that act on two controls

Looking through the standard WPF commands, such as copy/paste, they seem to all work using one button and act on a textbox.
My question: how do I use commands when I have one button, but I need data to be set in two separate controls(a textbox and a combobox). If the user has written text in textbox, but not selected a combobox value, then CanExecute should fail. This applies if combobox has been set, but not the textbox.
In my case specifically, all these controls are wrapped in a tabitem. As well, I have another tab with only a textbox and a button. I want it to have the same functionality as the first tab, except, instead of checking for the combobox value, it should detect that there is no combobox and pass in a default 'null object' value instead.
The Execute method should call a method in my viewmodel and pass in values from the combobox and textbox. As well, each tab should pass in another unique static value; i think i can handle this using commandparameter though.
How do I make this work? Do I make the parent tab that commandtarget and directly reference its children controls in the can/execute methods?
You need to implement CanExecute method that checks both TextBox databinding value and ComboBox.SelectedItem databinding value.
Take example from your question.
Your TextBox.Text should be databinding to your ViewModel
And as well as your ComboBox.
So your ViewModel should have two Properties:
public string TextBoxCurrentText {get { ...}set {...}}
public string ComboBoxCurrentSelected {get { ...}set {...}}
Then in both Setter, you would do your YourCommmand.RaiseCanExecuteChanged();
So it will execute your CanExecute code piece to determines can your Button be click.
Which can be:
bool YourCommandCanExecute()
{
//Just example
if (!string.IsNullOrEmpty(TextBoxCurrentText) && !string.IsNullOrEmpty(ComboBoxCurrentSelected))
return true;
return false;
}

WPF - Overriding IsVisible on my custom control

I have a custom control (an Adorner) that wraps another control (a textbox).
public class MyCustomAdorner : Decorator
{
...
public MyCustomAdorner()
{
Child = new TextBox();
}
}
I want to be able to override the VisibilityChanged so that the MyCustomAdorner's event is only fired if the Child's visiblity changes, not the actual decorator. How would I go about this?
On a first approach I would try to bind the Adorner's Visibility to the TextBox's Visibility (not sure if this one works). This way, if the textbox changes visibility, the adorner will follow. If you bind them two way, then it will work the other way around too. So if you don't want it to work both ways, make sure you don't set the Adorner's Visibility.
If binding the Visibilities together doesn't work, you can try to declare a new property (for example a bool), that manages the visibilities, and bind the two Visibilities to that bool through a Converter. And when you want to change something around the Visibilities, you set this bool to a new value.
Overriding the VisibilityChange event doesn't sound good to me, also I'm not sure if you can even do that...

Silverlight - rebinding to a property?

I'm just getting started with silverlight.
Basically I have a silverlight user control that has various dataGrids and a combobox, their item sources set to the properties of a custom plain c# object.
My problem is that I have a dropdown list that when a user selects an item from the list a new row should appear in one of the grids.
All I'm doing is handling the SelectionChanged event and adding a new item to to a list in my custom object and setting the itemsource for the grid again. This doesnt seem to work; no row is added to the dataGrid
I have no idea how to force my grid to "rebind" to this property.
I've been reading about dependency properties, are these what I need?
Any pointers would be really appreciated.
The list you are binding against should be of the type ObservableCollection. Then the datagrid should display the new item automatically .
The problem is that when you assign the same List to the ItemsSource the DataGrid knows its the same List so it does nothing.
As Henrik points out you should expose an Observable<T> not a List<T> for properties that are to be bound to ItemsSource properties of multi-item controls such as DataGrid, ListBox etc.
In addition your "plain c# objects" should implement the INotifyPropertyChanged interface if you want changes made by code to these properties to automatically appear in the UI.
What you probably want to do is update the binding source - which is relatively easily done.
private void ComboBox_SelectionChanged(object sender, RoutedEventArgs e)
{
this.dataGrid.GetBindingExpression(DataGrid.ItemsSource).UpdateSource();
}
This is a tad hack-y but will do what you need it to do. Implementing INotifyPropertyChanged is another great suggestion.
Silverlight show have some great info on INotifyPropertyChanged here

How to make ListView change ItemControl to VirtualizingStackPanel at runtime

OK, so, I have a ListView-derived control that changes Grouping and ItemsSource on the fly. When I group such that the scrollbars dissapear, and then change my ItemsSource to a different ICollectionView, my scrollbars do not return.
The basic problem is that ListView changes to a VirtualizedStackPanel when grouping is activated and does not change back when grouping is de-activated.
I don't mind that virtualization is disabled when grouping--this is not a problem. What I need is a way to make the ListView regenerate it's ItemPanel when I change the ItemsSource.
Could you add an event handler to the SourceUpdated event and then reset the ItemsPanelTemplate to a template defined in your Resources?
Something like:
public MyWindow()
{
InitializeComponent();
MyListView.SourceUpdated += new EventHandler<DataTransferEventArgs>( OnSourceUpdated );
}
void OnSourceUpdated( object sender, DataTransferEventArgs e )
{
MyListView.ItemsPanel = (ItemsPanelTemplate)Resources["MyItemsPanelTemplate"];
}

In WPF, is it possible to have a combo box control, that looks like a RadioButton?

I have a whole bunch of code that is dependent on the ComboBox type, and I want to be able to use it on a new UI, but the UI that I want to use it for needs to look like a RadioButton for usability reasons. Is it possible to have a ComboBox control look like a set of RadioButtons?
My suggestion would be to use an ItemsControl with a DataTemplate that would render RadioButtons. To the ItemsControl you'd bind the same thing you're binding to the ComboBox.
One caveat is that you need to set the GroupName of the radio buttons to something that would be the same to the group, so they can be mutually exclusive. Otherwise, if you don't do anything, you'll be able to select more than one RadioButton simultaneously.
You could build a new UserControl that has many of the same methods that the ComboBox class does, but adapt it so that it creates multiple radio boxes instead.
Your question is kinda vague though.
IE create an Items collection on your user control, and when something is added, draw a radio box and resize your control, instead of what a combo box does and just adds a string to the list.
Then all you have to do is find and replace all your references to ComboBox with RadioIFiedComboBox.
Heres some comparison:
ComboBox cb = new ComboBox();
cb.Items.Add("blah");
or
RadioIFiedComboBox cb = new RadioIFiedComboBox();
cb.Items.Add("blah");
and
public class RadioIFiedComboBox : UserControl {
public ObservableCollection<object> Items = new ObservableCollection<object>();
public RadioIFiedComboBox() {
Items.CollectionChanged += new NotifyCollectionChangedEventHandler(YourCollectionChanged);
}
private void YourCollectionChanged(){
//do something here to redraw your controls
}
}
The code above is just an example, you'd have to create all the methods you use in the ComboBox class and create similar functionality.

Resources