I have an ItemsControl object and am setting the DataTemplate to hold a Grid with a couple controls in it. The controls are databoud to a collection of some object MyObj, specifically a TextBlock and a ComboBox. MyObj has its own collection inside of it for a property. If that property has only 1 object in its collection, only the TextBlock is visible. But if there is more than 1 object in the collection, the TextBlock is visible and the ComboBox becomes visible once the TextBlock is clicked on.
I have the ComboBox filled up with what it needs, I just can't figure out how to specify which ComboBox needs to become visible when the TextBlock is Clicked on.
I guess my question is, how would I even go about doing this? Or, is there a better way to think about this problem?
I'm new to databinding in Silverlight and running into a bunch of issues on my own. Any help is always appreciated. Thank in advance.
One thing that you could do is add an extra property to the data item that you binding to, something like 'IsSelectionAvailable'. Make the visibility of your combobox bound to this property (via a boolean to Visibility enum Value Converter). Finally, add a click event handler for the text box that sets the IsSelectionAvailable property to true for the object it is bound to.
Hope that helps.
Related
I have a WPF ComboBox which I'm using to search names. I use the MVVM pattern and it's all pretty simple:
The ComboBox Text property is bound to a "SearchString" property on the VM. The ComboBox ItemsSource is bound to a "SearchResult" property on the VM. This is a list of objects displayed using a DataTemplate. The ComboBox also triggers a "PreviewKeyDown" event and pressing enter selects the first item in the result set, with up and down arrow keys traversing the results. The SelectedItem is bound to the DataContext for a GroupBox. This part works really nicely.
When an item is selected in the ComboBox, WPF is automatically attempting to replace "Text" with my SelectedItem. This causes my results set to get emptied and "Text" to revert to an empty string.
The behaviour I'd like is that when an item is selected, the text in the ComboBox remains exactly the same, so that my user can continue to traverse the result set using up and down arrows.
Is there an elegant way to achieve this? I think that nothing will be added to the question with a code snippet, but happy to supply if wanted.
The behaviour I'd like is that when an item is selected, the text in the ComboBox remains exactly the same, so that my user can continue to traverse the result set using up and down arrows.
That's a requirement that's not built into the ComboBox control. If you want something like that, you'll have to build it yourself (and subclassing most likely won't help, you'll have to build most of a ComboBox from scratch for this).
In fact you shouldn't be binding the current item like that either, you should use the SelectedItem property, which doesn't do any conversions or copying, exactly what you want for an internal binding.
I have a series of WrapPanels within a DockPanel. I want all but the top panel to be disabled at the beginning but all panels to be visible. As the user satisfies conditions in one panel I want to enable another panel. However, I can't figure out how I can bind the IsEnabled property of the WrapPanel (or if I need to the individual elements) to a boolean in my ViewModel. Any idea?
Update2: This works amazingingly! Adding a convention for IsEnabled to Caliburn.Micro
Update: Oops I lied. It keeps resetting all of my XAML by having an object of the same type in the ViewModel.
Just realized that I can just create an instance of what I am trying to >enable/disable in the ViewModel and from that access the IsEnabled property. Not >direct but works!
I basically want to create something like this:
So, a user can add/remove items from the list and edit them in the red panel below the list. When the item is selected, the changes can be made in the panel.
Then, the changes can be either saved or canceled with one of the buttons below. User cannot select another item in the list without explicitly cancelling the changes.
How to do this? I only see the option of making the red panel a separate control and changing its DataContext manually on ListView.SelectedItem changes. The red panel's DataContext is a special wrapper on a ListView's item which has 'save' and 'cancel' options. ListView is set to IsEnabled = False so that its SelectedItem doesn't change when editing is in progress.
How would you do this?
The question is quite close from, for example, this one :
How do I stop binding properties from updating?
Anyway the WPF Object that will handle this is the BindingGroup :
http://msdn.microsoft.com/en-us/library/system.windows.data.bindinggroup.aspx
the most easy apporach is to use a dialog for edit a selecteditem. thats what i do in my project. i use this dialogservice and handle the result.
if you want to handle all in one view you could set a property SelectionEnabled=false when the SelecteItem is set. and then SelectionEnabled=true when the save or cancel command is invoked.
the datacontext for your edit panel is simply your SelectedItem.
You can try to use bindings with UpdateSourceTrigger=Explicit. The blog post Edit With Explicit UpdateSourceTrigger will give you more information about how this can be implemented.
I have a listbox bound to a List<object> as its DataSource. What I'm wanting to do is use the SelectedValue property of the Listbox (i.e the object corresponding to the current selection) as a DataSource for some textboxes that will display certain values of the object for editing.
I've tried
TextBox.DataBindings.Add(new Binding("Text", ListBox, "SelectedValue.name"));
and
TextBox.DataBindings.Add(new Binding("Text", ListBox.SelectedValue, "name"));
but as there is nothing selected in the ListBox (because the form hasn't been shown yet), I get an exception about "Value cannot be null".
Now I know that I can (re)bind to ListBox.SelectedValue in my form's SelectionChangeCommitted handler (that is, after a selection has been made), but if i have to do that I might as well just set the TextBox's value directly (admittedly I could just do this to resolve the issue, but I'd like to learn more about databinding).
So my question is, in short: Is it possible to bind to ListBox.SelectedValue once (initially, before the ListBox has a selection) and avoid the null value exception, and if so, how?
I'm not sure which control your projectNameCtrl is, but you'll want to bind your TextBox. Something like this:
textBox1.DataBindings.Add(new Binding("Text", listBox1, "selectedvalue"));
Where:
textBox1 is your TextBox
listBox1 is your ListView
EDIT
You should be able to data bind a ListBox even if that ListBox has no selected items so your 'value cannot be null' must be for another reason. I suggest using the debugger to determine which object specifically is null.
You can ensure you don't data bind a control more than once by first checking the control's DataBindings.Count property; if it's equal to zero you haven't yet data bound that control:
if (textBox1.DataBindings.Count == 0) {
// OK to data bind textBox1.
}
Off the top of my head, I think you'd need to do something on each selectedItemChanged event...
I know this doesn't answer your question, but I'd look at using WPF instead since this is so much more elegant to do in WPF, and let's face it, by not creating a GUI in code (using XAML instead) your sanity will be much more intact when you finish your project. I don't recall enough windows forms, but in WPF, you just implement INotifyPropertyChanged on your back-end object that you're binding to, and then when you bind to the SelectedItem property of that ListBox, you automatically get updates since the SelectedItem property is a DependencyProperty.
The following code works as you’d expect — MyProperty on the model is updated when the user picks a new item in the dropdown.
comboBox1.DataBindings.Add("SelectedValue", myModel, "MyProperty", true,
DataSourceUpdateMode.OnPropertyChanged);
The following, however, doesn’t work the same way and the model update isn’t triggered until the input focus moves to another control on the form:
comboBox1.DataBindings.Add("SelectedItem", myModel, "MyProperty", true,
DataSourceUpdateMode.OnPropertyChanged);
Does anybody know why? I don’t even know where to start investigating the cause. Pointers in the right direction to start the investigation or an outright explanation would be equally appreciated.
Aside: for my purposes, I ended up binding to both SelectedItem and SelectedValue. This way I get instant model updates based on UI changes (through the SelectedValue binding), and UI updates based on programmatic model changes (through the SelectedItem binding).
The ComboBox control inherits from the ListControl control.
The SelectedItem property is a proper member of the ComboBox control. The event that is fired on change is ComboBox.SelectionChangeCommitted
ComboBox.SelectionChangeCommitted
Occurs when the selected item has changed and that change is displayed in the ComboBox.
The SelectedValue property is inherited from the ListControl control.
As such, this property will fire the ListControl.SelectedValueChanged event.
ListControl.SelectedValueChanged
Occurs when the SelectedValue property changes.
That said, they won't fire the INotifyPropertyChanged.PropertyChanged event the same, but they will anyway. The only difference is in the firing event. SelectedValueChanged is fired as soon as a new selection is made from the list part of the ComboBox, and SelectedItemChanged is fired when the item is displayed in the TextBox portion of the ComboBox.
In short, they both represent something in the list part of the ComboBox. So, when binding either property, the result is the same, since the PropertyChanged event is fired in either case. And since they both represent an element from the list, the they are probably treated the same.
Does this help?
EDIT #1
Assuming that the list part of the ComboBox represents a property (as I can't confirm since I didn't write the control), binding either of SelectedItem or SelectedValue affects the same collection inside the control. Then, when this property is changed, the same occurs in the end. The INotifyPropertryPropertyChanged.PropertyChanged event is fired on the same property.
I suspect that the SelectedItem property of the ComboBox does not change until the control has been validated (which occurs when the control loses focus), whereas the SelectedValue property changes whenever the user selects an item.
Here is a reference to the focus events that occur on controls:
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.validated.aspx
This is a long-standing "feature" of the list controls in .NET in my experience. Personally, I would just bind to the on change of the SelectedValue property and write whatever additional code is necessary to workaround this "feature" (such as having two properties, binding to one for SelectedValue, and then, on the set of that property, updating the value from SelectedItem in your custom code).
Anyway, I hope that helps =D
If you want Selected.Value being worked
you have to do following things:
1. Set DisplayMember
2. Set ValueMember
3. Set DataSource (not use Items.Add, Items.AddRange, DataBinding etc.)
The key point is Set DataSource!
If we want to bind to a dictionary ie
<ComboBox SelectedValue="{Binding Pathology, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{x:Static RnxGlobal:CLocalizedEnums.PathologiesValues}" DisplayMemberPath="Value" SelectedValuePath="Key"
Margin="{StaticResource SmallMarginLeftBottom}"/>
then SelectedItem will not work whilist SelectedValue will