Bind silverlight combobox to the result of another combobox - silverlight

I want to do something like this:
<combobox x:Name="cboCustomers" ItemsSource="{Binding Path=Data.Customers}"/>
<combobox x:Name="cboInvoices"ItemsSource="{cboCustomers.SelectedItem.Invoices}"/>
Anyone know of a way to do something like this in Silverlight 3? I am sure there is some information about it out there, but I am having bad luck with Google in forming the question.

You need to specify ElementName on the second binding:
<combobox x:Name="cboCustomers" ItemsSource="{Binding Data.Customers}"/>
<combobox x:Name="cboInvoices"ItemsSource="{Binding SelectedItem.Invoices, ElementName=cboCustomers}"/>
If you also want the second combobox to be disabled until something has been selected in the first combobox you can bind the IsEnabled property of the second combobox to the SelectedItem property of the first combobox through a converter.
Add this class to your project:
public class NullToBooleanConverter : IValueConverter {
public Object Convert(Object value, Type targetType, Object parameter, CultureInfo culture) {
if (targetType == typeof(Boolean))
return value != null;
throw new NotSupportedException("Value converter can only convert to Boolean type.");
}
public Object ConvertBack(Object value, Type targetType, Object parameter, CultureInfo culture) {
throw new NotSupportedException("Value converter cannot convert back.");
}
}
Add an instance of this class to the resource dictionary of your user control (local is the namespace tag for the namespace of the converter):
<UserControl.Resources>
<local:NullToBooleanConverter x:Key="NullToBooleanConverter"/>
</UserControl.Resources>
Then you can add this to the second combobox:
IsEnabled="{Binding SelectedItem, ElementName=cboCustomers, Converter={StaticResource NullToBooleanConverter}}"

You'd be looking at a Cascading Combobox
http://weblogs.asp.net/manishdalal/archive/2008/10/22/cascading-combobox.aspx

Related

How do I bind a DataGrid Width to a converter?

I want to include the size of the VerticalScrollbar when i define the width of a DataGrid.
So far i wrote a Converter:
[ValueConversion(typeof(double), typeof(double))]
public class VerticalScrollbarConverter : IValueConverter
{
#region IValueConverter Member
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is double)
return (double)value + SystemParameters.VerticalScrollBarWidth;
else
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
I included my converter in the xaml namespace with:
xmlns:Core="clr-namespace:Core;assembly=SMS_Core"
And I defined the converter as a (window) resource:
<Window.Resources>
<Core:VerticalScrollbarConverter x:Key="VerticalScrollbarConverter"/>
</Window.Resources>
Since all of my DataGrid.Columns have a fixed Value I know the value that i need to pass.
How do I tell my GridView Width property in xaml to use the converter?
I know that my question is pretty basic. As you can tell I am very new to WPF.
Thanks in advance for every hint. If you need some more info or context just ask away.
The comment from sa_ddam213 didn't exactly solve the problem. But it sure did push me into the right direction.
To pass the value automatically I had to do the following:
I created a property in the window class called TotalColumnWidth. Returning this:
myDataGrid.Columns.Sum(c => c.ActualWidth);
The xaml is the following:
Width="{Binding ElementName=_Root, Path=TotalColumnWidth, Converter={StaticResource ResourceKey=VerticalScrollbarConverter}}"
Using the converter mentioned above.

In Silverlight how do I set a buttons enabled state to be enabled based on items selected in a listbox?

I have a dialog that contains a listbox and the customary ok, cancel buttons. I would like set the enabled state of the ok button to be enabled only if an item in the listbox has been select. I would like to do this with bindings rather than in the code behind.
I may have been going down the wrong route but I have being trying to do something like the following
IsEnabled="{Binding ElementName=ProjectList, Path=??? }"
As you can probably see I have no idea what would go in the "Path"
If ProjectList is the name of the list box then you should be able to use SelectedItem.
You will need to bind through a converter that checks for the SelectedItem being null and returning false in that case.
So your XAML becomes:
IsEnabled="{Binding ElementName=ProjectList, Path=SelectedItem, Converter={StaticResource SelectedItemToBool}}"
and the selector looks something like this:
public class SelectedItemToBool : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value != null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

How do I sort a WPF TreeView using the HierarchicalDataTemplate for EntityCollection objects?

My Webpage is an Entity Framework entity. These are bound to a WPF TreeView. I want to order all the Webpages shown in the TreeView on the Sort property.
Code
EDMX
Its Subordinates property returns a collection of zero or more Webpages.
XAML
<TreeView Name="TreeViewWebpages">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Webpage}"
ItemsSource="{Binding Subordinates}">
<TextBlock Text="{Binding Path=Title}" />
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
C#
TreeViewWebpages.ItemsSource = from Webpage root in db.Webpages.Include("Subordinates")
where root.Dominant == null
select root;
Result
Webpages are unordered within the TreeView.
Problem
How do I change this to order all the Webpages shown in the TreeView on the Sort property?
Update
This ValueConverter seems to work (Thank you #KP Adrian and #IVerzin). Is there a better way?
XAML
ItemsSource="{Binding Path=Subordinates, Converter={local:SortConverter}}"
C#
[ValueConversion(typeof(EntityCollection<Webpage>), typeof(EntityCollection<Webpage>))]
public class SortConverter : MarkupExtension, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((EntityCollection<Webpage>)value).OrderBy(o => o.Sort);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
}
Assuming your Sort property is a string or integer you are using to determine the order at runtime, you can add an orderby section to your expression.
TreeViewWebpages.ItemsSource = from Webpage root in db.Webpages.Include("Subordinates")
where root.Dominant == null
orderby root.Sort
select root;

wpf converter binding - dynamic binding in wrong order

I am trying to bind a combobox with the Tabitems using converter
My converter class is as follows
public class TabItemsCollection : IValueConverter
{
>public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
ItemCollection collection = value as ItemCollection;
IList<string> names = new List<string>();
foreach (TabItem ti in collection.SourceCollection)
{
names.Add(ti.Header.ToString());
}
return names;
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
My xaml is as follows
//combobox
<ComboBox Name="cmbModule"
ItemsSource="{Binding ElementName=mnuMain, Path=Items, Converter={StaticResource MenuItemsConverter}}" SelectedIndex="{Binding ElementName=mnuMain, Path=SelectedIndex}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
//TabControl
<local:MenuTab Name="mnuMain"></local:MenuTab>
I am binding 'mnuMain' with items which is a custom tabcontrol in codebehind, as i am doing so i am unable to popularate combobox with tabitems because the converter fires first and then the 'mnuMain'. If I create the Tabitems in xaml the combobox is populated with tabitems but my problem is with dynamic binding.
There is a way to force your binding to update again:
cmbModule.GetBindingExpression(ComboBox.ItemsSourceProperty).UpdateTarget();
Another option is to create a DependecyProperty that holds the collection of tabs and then bind the Combobox and MenuTab to the same property. the SelectedIndex can be done in the same way as you do now.
A third option is to create a property of type ObservableCollection that holds the information that is needed and then create 2 Converters, one to convert to tabitem and 1 to convert to Combobox item. If you add or remove an item from the collection will the binding be triggered automatically.

WPF bind IsEnabled on other controls if a listbox has a select item

I have a grid with 2 columns, a listbox in column 0 and a number of other controls in the a secondary grid in the main grids column 1.
I want this controls only to be enabled (or perhaps visible) if an items is selected in the listbox through binding. I tried on a combo box:
IsEnabled="{Binding myList.SelectedIndex}"
But that does not seem to work.
Am I missing something? Should something like this work?
thanks
You'll need a ValueConverter for this. This article describes it in detail, but the summary is you need a public class that implements IValueConverter. In the Convert() method, you could do something like this:
if(!(value is int)) return false;
if(value == -1) return false;
return true;
Now, in your XAML, you need to do:
<Window.Resources>
<local:YourValueConverter x:Key="MyValueConverter">
</Window.Resources>
And finally, modify your binding to:
IsEnabled="{Binding myList.SelectedIndex, Converter={StaticResource MyValueConverter}"
Are you sure you didn't mean
IsEnabled="{Binding ElementName=myList, Path=SelectedIndex, Converter={StaticResource MyValueConverter}"
though? You can't implicitly put the element's name in the path (unless the Window itself is the DataContext, I guess). It might also be easier to bind to SelectedItem and check for not null, but that's really just preference.
Oh, and if you're not familiar with alternate xmlns declarations, up at the top of your Window, add
xmlns:local=
and VS will prompt you for the various possibilities. You need to find the one that matches the namespace you put the valueconverter you made in.
Copy-paste solution:
Add this class to your code:
public class HasSelectedItemConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value is int && ((int) value != -1);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Add converter as StaticResource to App.xml in <Application.Resources> section:
<local:HasSelectedItemConverter x:Key="HasSelectedItemConverter" />
And now you can use it in your XAML:
<Button IsEnabled="{Binding ElementName=listView1, Path=SelectedIndex,
Converter={StaticResource HasSelectedItemConverter}"/>
Hmm, perhaps it works with a BindingConverter, which converts explicitly all indexes > 0 to true.

Resources