WPF Databinding to ComboBox and also toggle its visibility - wpf

There are two issues that iam facing. One is binding a collection to combobox
In code:
private ObservableCollection<string> errList;
Initially its empty and then i add items to it.
In XAML:
<comboBox ItemsSource="{Binding errList}" IsSynchronizedWithCurrentItem="True"
Isnt this enough to get it done. But no items are seen in the combobox.
Second is toggling the visibility of the combobox when items are present.
<combobox Visibility="{ Binding ElementName=Page1, Path=ItemsPresent, Converter={StaticResource booltoVis} }"
ItemsPresent is a property which returns true of errList has items more than 0. But this is not working.
Please Help

I don't think you can bind to a private field, instead after filling your collection you can do the following:
YourComboBoxName.ItemsSource = errList;
For the visibility you need to do self binding like this:
<ComboBox Visibility="{Binding Path=ItemsPresent, RelativeSource={RelativeSource Self}, Converter={StaticResource booltoVis}}"/>

Related

Bind to a Property in the Data Context from a ListviewItem

I have a data context in the form of MyViewModel.
MyViewModel has a property: public int MyWidth.
For each item in my listview, that is ListViewItem, I need to display a canvas with a width equal to MyWidth.
My listView has it's ItemSource bound to a property called MyCollectionOfInts.
Which, as you may have guessed, is of the following definition: ObservableCollection<int>.
The astute reader has likely realized, the data context of myListView is int and thus fails when trying to bind the non-existant MyWidth property from the int type data-context.
What kind of theoretical crazy binding is necessary to get this kind of nutty thing to work?
My most recent attempt was to bind using RelativeSource but couldn't exactly figure it out...
My list View:
<ListView Name="MyListView" ItemsSource="{Binding MyCollectionOfInts}"
My Items within the List view.
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumns Header=MyInts">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Label Name="m_TestLabel" Content="ASDF" />
<TextBox Text="{Binding Path=MyWidth, RelativeSource=????{RelativeSource AncestorType={x:Type MyViewModel}}}"/>
</DataTemplate>
</...a bunch of close brackets>
My list view Item is an int, but I want to get the Control's original data-context, ie. myViewModel, and bind the canvas width of my ListViewItem to the MyWidth property of myViewModel. How can I get the ListViewItem to recognize the control's data-context?
Note: I don't really want to make a container for the ListView and store a static MyWidth variable in it, but if that is the only way, then let me know. I'm hoping it's not.
Try this:
<TextBox Text="{Binding Path=DataContext.MyWidth, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"/>
If your View is usercontrol else use Window in type
<TextBox Text="{Binding Path=DataContext.MyWidth,
RelativeSource={RelativeSource AncestorType={x:Type ListView }}}"/>
Or
<TextBox Text="{Binding Path=DataContext.MyWidth,
Source={x:Reference MyListView}"/>

ComboBox doesn't show current value of assigned field inside a ListView

I have a DataTemplate with a Combobox inside a ListView like this
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding DataContext.Dimensions, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}}"
DisplayMemberPath="Description"
SelectedValuePath="Id"
SelectedItem="{Binding DimName}"/>
</DataTemplate>
The combobox is populated correctly, but it doesn't select the content according to underlying field (ie. Dimension.DimName).
Here's how the ListView is declared
<ListView
Name="lstCriteria"
ScrollViewer.VerticalScrollBarVisibility="Auto"
Margin="5"
AlternationCount="2"
ItemContainerStyle="{StaticResource CriteriaItemStyle}"
ItemsSource="{Binding Source={StaticResource CriteriaList}}" DockPanel.Dock="Top"
IsSynchronizedWithCurrentItem="True">
If I replace combobox with a TextBlock it does show the DimName Field's value, like this
<TextBox Text="{Binding DimName}"/>
What am I missing ?
Does your DimName come directly from the Dimensions list?
By default, if a ComboBox's Items is set to a custom class, it will compare the SelectedItem to an item in the ItemSource by reference. It will not match the item if they do not refer to the exact same object in memory, even if the object's data is the same.
To get around that you can either set SelectedValue and SelectedValuePath instead of SelectedItem on your ComboBox, or you can overwrite the Equals() method of your DimName class to return true if an object's data is equal
Edit
In regards to your comment below, is DimName a Dimension object? If so then setting SelectedItem should work fine. If it's an long you'll need to set SelectedValue, not SelectedItem. If it's something else, you may need a converter to convert it into a Dimension object
As Rachel suggested, I added a new Property to my class called Dimension of class Dimension like this
public Dimension Dimension
{
get { return _dimension; }
set { _dimension = value; }
}
and then set SelectedItem="{Binding Dimension}" as follows,
<ComboBox ItemsSource="{Binding DataContext.Dimensions, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}}"
DisplayMemberPath="Description"
SelectedValuePath="Id"
SelectedItem="{Binding Dimension}">
</ComboBox>
The silly mistake I was making was,
As my combobox was populating correctly, I was hoping that WPF will somehow match the DimName content with one of the items in the ComboBox automatically, which is not possible.

Silverlight data bind combobox items and value separately

I can use databinding to bind the contents of a combobox to a collection, or I can bind the selected value in the combobox to a member of a class, but I can't do both at the same time. I want to be able to bind the contents to one thing and the selected value to something else, I guess the combobox can't handle two datacontexts or I'm not specifying them explicitly. Example below, I'd appreciate any help! Thanks.
In XAML:
<ComboBox Name="Combo" ItemsSource="{Binding}"
SelectedValue="{Binding ID, Mode=TwoWay}"/>
In code:
LayoutRoot.DataContext = myClass;
Combo.DataContext = items;
This should do it for you, or at least be close.
<Grid DataContext="{Binding Source=MyObject}">
<ComboBox x:Name="Combo"
ItemsSource="{Binding Source=MyCollection}"
SelectedValue="{Binding Path=ID, Mode=TwoWay}"/>
</Grid>

access the Window's DataContext from within a DataGrid

I have some problem to access the Window's DataContext from within a DataGrid.
The DataGrid is bound to a IBindingList:
public IBindingList Items{ get; set; }
private void initItems()
{
//ItemFactory is a Linq2SQL Context, Items is the view of availabe Items
this.Items = this.ItemFactory.Items.GetNewBindingList();
}
From within my xaml I try to get those data to fill a ComboBox:
<DataGridComboBoxColumn Header="Typ"
DisplayMemberPath="Description"
SelectedValuePath="ItemID"
ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Mode=OneWay, Path=DataContext.Items, UpdateSourceTrigger=PropertyChanged}" />
But it doesn't work. I tried out many variants already. The ComboBox gets not populated.
Any help greatly appreciated!
Note:
The following ComboBox in the same Window does work:
<ComboBox x:Name="workingCombo" ItemsSource="{Binding Path=Items}" DisplayMemberPath="Description" SelectedValuePath="ItemID" />
The DataGridComboBoxColumn is not directly connected to the visual tree and therefore the FindAncestor-operation will fail (and also the DataContext will not be inherited).
The most simple solution is to
create a ViewModel for each line and provide there in the ItemsSource
for the ComboBox.
Using a DataGridTemplateColumn and placing the ComboBox in the
DataTemplate helps.
Here
is a another post concerning this problem. And look also at this
post.

How to get number of items in ObservableCollection from XAML?

I'm displaying all of my customers which I get from a ViewModel ObservableCollectoin property within a ComboBox like this:
<ComboBox
ItemsSource="{Binding Customers}"
ItemTemplate="{StaticResource CustomerComboBoxTemplate}"
Margin="20"
HorizontalAlignment="Left"
SelectedItem="{Binding SelectedCustomer, Mode=TwoWay}"/>
Is there a way to get the number of items in the ObservableCollection without creating another ViewModel property, e.g. something like this:
PSEUDO-CODE:
<TextBlock Text="{Binding Customers.Count()}"/>
The ObservableCollection type exposes a Count Property which you can use.
I don't know if ObservableCollection raises the PropertyChanged event in order to inform the UI about updates to this property though.

Resources