wpf binding to string - wpf

I have a Movie class with a Dim _characters = New ObservableCollection(of String)
Characters is the associated property to get and set
How can i get characters to show up in the listBox using Binding?
So far i have the following, this isn't working as i don't know what to put instead of ToString.
<ListBox Name="cList" ItemsSource="{Binding Characters}">
<ItemsControl >
<ItemsControl.ItemTemplate >
<DataTemplate >
<TextBox Text="{Binding ToString}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ListBox>
I want them to be editable, hence a textbox.
i tried to bind Characters to TextBox directly, even that didn't work.
Edit :
in the code i have parentGrid1.DataContext = me.movies where
parent grid holds movies.

For those who are experiencing the exception
... binding requires path or xpath ...
You can bind the object directly this way:
<Label Content="{Binding .}" />

Change your TextBox binding to the following. I think it should work:
<TextBox Text="{Binding}"/>
This loads the item itself instead of a property or method output. Since the item is a string it should bind to the strings value.

You cannot perform two-way binding to ObservableCollection<string>. In order to make the strings editable you have to create a class with a string get/set property as the following class Foo:
public class Foo
{
string _text;
public Foo(string text)
{
_text = text;
}
public string Text
{
get { return _text; }
set { _text = value; }
}
}
Your Characters should then be of type ObservableCollection<Foo> and your XAML should be changed so that the textboxes are binding to Foo.Text:
<ListBox ItemsSource="{Binding Characters}" >
<ListBox.ItemTemplate >
<DataTemplate >
<TextBox Text="{Binding Text}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Just remove the ToString portion of the code.
Currently you are telling the program that you want to bind to an object called ToString

I take it that Characters is a public property. Debug and be sure that get is being called for Characters. If you have a the datacontext of the page/window to Movies then you need ItemsSource on the ListBox to be {Binding Path=Characters}

Related

MVVM WPF - ComboBox two way binding inside ItemsControl

I am working on this problem for about a day now.
For some reason I am unable to TwoWay bind a value to a ComboBox if it is inside a ItemsControl. Outside works just fine.
I have an ObservableCollection of int? in my ViewModel:
private ObservableCollection<int?> _sorterExitsSettings = new ObservableCollection<int?>();
public ObservableCollection<int?> SorterExitsSettings
{
get { return _sorterExitsSettings; }
set
{
if (_sorterExitsSettings != value)
{
_sorterExitsSettings = value;
RaisePropertyChanged("SorterExitsSettings");
}
}
}
My XAML:
<ItemsControl ItemsSource="{Binding SorterExitsSettings}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl}, Path=DataContext.ScanRouter.Stores}"
SelectedValue="{Binding Path=., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="name" SelectedValuePath="id" IsEditable="True" />
</DataTemplate>
</ItemsControl.ItemTemplate>
So the ComboBox is populated with a list of stores. It works fine so far.
The ObservableCollection SorterExitsSettings even has some values set which are shown in the displayed ComboBoxes. So setting the SelectedValue also works.
However when I change a selection, SorterExitsSettings wont change. While when I implement the ComboBoxes(100) without an ItemsControl it suddenly works fine.
<ComboBox ItemsSource="{Binding ScanRouter.Stores}" DisplayMemberPath="name" SelectedValuePath="id" IsEditable="True" SelectedValue="{Binding SorterExitsSettings[0], Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
Even better when I implement the ComboBoxes using the ItemsControl and also the example ComboBox shown above. When I change the single ComboBox's value it will change the value of the ComboBox inside the ItemsControl, but not the other way around.
Did somebody encounter this problem before?
My guess was that the ItemsControl doesn't like the fact that I am binding my selected value to an item in a list. However when I bind directly to a ViewModel property(Store) it also doesn't work.
I also tried using SelctedItem instead of SelectedValue and populate the ObservableCollection with Store objects instead of int?.
The problem is that you're binding your ComboBox's SelectedValue directly to the collection elements which are type int ?. This won't work, binding targets have to be properties. Try wrapping your int ? values in a class and expose the value as a property of that class with a getter and setter, i.e. something like this:
private ObservableCollection<Wrapper> _sorterExitsSettings = new ObservableCollection<Wrapper>();
... etc...
And:
public class Wrapper
{
public int? Value {get; set;}
}
And finally:
<ComboBox ... SelectedValue="{Binding Path=Value, Mode=TwoWay...
Post back here if you still have problems.

Binding TwoWay to SelectedItem: "Wrong way" synchronization on initialization

I am trying to bind a property of my DataContext to the SelectedItem on a ComboBox like this:
<ComboBox x:Name="ElementSelector"
ItemsSource="{Binding Source={StaticResource Elements}}"
DisplayMemberPath="ElementName"
SelectedItem="{Binding ValueElement, Mode=TwoWay}">
where the Elements resource is a CollectionViewSource (don't know, whether this matters).
When everything is initialized, the property ValueElement of the DataContext is set to the first item in the CollectionViewSource. What I want, is to initialize it the other way around: I would like to set SelectedItem of the ComboBox to the value of the property or null if no matching item is contained.
How can this be done?
EDIT - Additional information:
The ComboBox is part of a DataTemplate:
<DataTemplate x:Key="ReferenceTemplate"
DataType="viewModels:ElementMetaReferenceViewModel">
<StackPanel Orientation="Horizontal">
<StackPanel.Resources>
<ResourceDictionary>
<views:ElementsForReferenceViewSource x:Key="Elements"
Source="{Binding DataContext.CurrentProject.Elements, ElementName=Root}"
ReferenceToFilterFor="{Binding}"/>
</ResourceDictionary>
</StackPanel.Resources>
<TextBlock Text="{Binding PropertyName}"/>
<ComboBox x:Name="ElementSelector"
ItemsSource="{Binding Source={StaticResource Elements}}"
DisplayMemberPath="ElementName"
SelectedItem=""{Binding ValueElement, Mode=TwoWay}" />
</StackPanel>
</DataTemplate>
The ElementsForReferenceViewSource simply derives from CollectionViewSource and implements an additional DependencyProperty which is used for filtering.
The DataContext of the items in the CollectionViewSource look like this:
public class ElementMetaReferenceViewModel : ViewModelBase<ElementMetaReference, ElementMetaReferenceContext>
{
...
private ElementMetaViewModel _valueElement;
public ElementMetaViewModel ValueElement
{
get { return _valueElement; }
set
{
if (value == null) return;
_valueElement = value;
Model.TargetElement = value.Model;
}
}
...
}
For people encountering the same issue
The above code works as expected. The solution was getting the stuff behind the scenes right. Make sure, that the instance of the ViewModel which is the value of the property you want to bind to is definitely contained in the CollectionViewSource.
In my case the issue was deserializing an object tree incorrectly, so objects were instantiated twice. Then for each object a distinct ViewModel was initialized and then obviously the value of the property was not contained in the list.
Remark
To check whether this is an issue in your case, you can try the following:
Override the ToString() methods of the ViewModels displayed in the ComboBox like this:
public override string ToString()
{
return "VM"+ Model.GetHashCode().ToString();
}
Then you can easily compare the items in the source collection with the value on your property. Not the most professional way, but it did the job for me.

How to bind a property in itemtemplate to a proptery in itemsource?

Consider this container:
public class ItemInfo : DependencyObject
{
public string Name { get; set; }
public ObservableCollection<SomeDataItem> DataValues { get; set; }
...
Dependency object registration and event handling
...
}
public class MyItemSource : ObservableCollection<ItemInfo>
{
...
}
Now, I wish to display this data in a listview where the control that displays the item is custom. For that, I'd set the MyItemSource to listview's ItemSource and define a ItemTemplate. However, it seems that I have no access to ItemInfo in the ItemTemplate. This is my XAML:
<Grid>
<ListBox ItemsSource="{StaticResource MyStaticDataSource}"
Grid.IsSharedSizeScope="True">
<ListBox.ItemTemplate>
<DataTemplate>
<local:ItemInfoUserControl x:Name="itemInfoUserControl"
Name = "{Binding Name}" <--- this doesn't work
Data = "{Binding DataValues}" <--- this doesn't work
Width="300" Height="200"
Grid.Row="1">
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
Instead of binding to ItemSource's ItemInfo, it binds to the ItemInfoUserControl properties, which is not what I wish it to do. Is there a way to bind properties in itemtemplate to a property in itemsource ? Or is there an alternative approach to what i'm ultimately trying to accomplish ?
Thanks!
Well, first of all you need to use proper binding syntax:
Name = "{Binding Name}"
and
Data = "{Binding DataValues}"
Instead of just "Name = "Binding Name"" and "Data = "Binding DataValues"". Note the addition of "{" and "}" around your binding expression.
This might be enough to solve your problem, as long as Name and DataValues are DependencyProperties in ItemInfoUserControl. If not, you'll need to implement them as DependencyProperties in order to be able to bind to them in XAML. See here for a good MSDN article on defining custom dependency properties.
Edit: Also, just noticed -- you're setting both x:Name and Name. From this article on MSDN:
If Name is available as a property on the class, Name and x:Name can be used interchangeably as attributes, but a parse exception will result if both are specified on the same element. If the XAML is markup compiled, the exception will occur on the markup compile, otherwise it occurs on load.
Remove x:Name="itemInfoUserControl" and see if that helps.

Silverlight 3 ComboBox ItemTemplate binding

I have a simple ComboBox in my Silverlight 3 application. I want to populate it from an ObservableCollection. The list holds a class that has a Name(string), and a Selected(bool) property. The combo box has as many items as I have in the list, but I cannot seem to get the list data to appear.
Any help would be appreciated.
<ComboBox x:Name="cmbCategory" Grid.Column="3">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"/>
<CheckBox IsChecked="{Binding Selected}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
...
private class cmbCategoryClass
{
public string Name { get; set; }
public bool Selected { get; set; }
}
private ObservableCollection<cmbCategoryClass> _categories;
....
cmbCategory.DataContext = _categories;
cmbCategory.ItemsSource = _categories;
I can't tell from your code if this is a Codebehind or a ViewModel. I am guessing that you are actually populating the _categories list in code so that it contains at least one cmbCategoryClass object. Try removing the line that sets the DataContext to _categories as your ItemsSource may be looking for a _categories property on the DataContext Check the Output window in Visual Studio when running in debug mode for clues to data binding failures.

wpf binding from a FindAncestor to Dependency Property of custom control

I've got a custom WPF control with a DependencyProperty MyString
I'm using the control within an ItemsControl on my View and want to fish a value out from the ViewModel.
As the DataContext of the control becomes each Item in the ItemsSource of the ItemsControl I thought I'd just be able to use FindAncestor but it dosnt seem to work ... can anyone see where I'm going wrong please?
Heres the XAML on the View ...
<Grid>
<ItemsControl ItemsSource="{Binding MyItems}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Name="myStack">
<ImportExceptions:ControlStrip MyString="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemsControl}}, Path=DataContext.MyStringOnViewModel}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
and heres the code behind my custom control where I've set up my dependency property ...
public partial class ControlStrip
{
public ControlStrip()
{
InitializeComponent();
}
public string MyString
{
get
{
return GetValue(MyStringProperty).ToString();
}
set
{
SetValue(MyStringProperty, value);
}
}
public static readonly DependencyProperty MyStringProperty =
DependencyProperty.RegisterAttached("MyString", typeof (string), typeof (ControlStrip));
}
The DataContext of the control doesn't change - the DataContext for the ImportExceptions:ControlStrip will be (unless explicitly specified) the next DataContext available as its goes 'up' the visual tree...
I infer from your code that you have set the DataContext of the View to a ViewModel with properties 'MyItems' and 'MyStringOnViewModel' - you should be able to simply bind the MyString property directly to the ViewModel, like
<ImportExceptions:ControlStrip MyString="{Binding Path=MyStringOnViewModel}" />
Your code looks fine. Probably you have made an error in the DataContext reference. In all likeliness the DataContext of the the ItemsControl already is MyStringOnViewModel. So, omit the .MystringOnViewModel after the DataContext in the Path attribute. If not can you give some more code, ore post a simplification of it that mimicks how the DataCon,text(s) is/are set?

Resources