Skip to main content
Home Forums Silverlight Programming Silverlight Controls and Silverlight Toolkit Setting properties on templated items in an ItemsControl
4 replies. Latest Post by JoostM on June 22, 2009.
(0)
JoostM
Member
0 points
4 Posts
05-29-2009 10:30 AM |
Hi, I have an ItemsControl with an ItemTemplate which binds the Text property of a TextBlock to a string property on my data object. For the interaction in the application I need to set some visual properties on all the items in the ItemsControl - for example, I need to set the TextWrapping value for all the items.
The only way I am able to do this is through data binding: I declare a TextWrapping property on my data object, and in the item template I can bind the TextBlock.TextWrapping property to the TextWrapping property on my data object.
However, TextWrapping has nothing to do with my data, so I defined a VisualObject<T> class which has these visual properties like TextWrapping and which wraps the data object I want to show and which exposes the visual properties I don't want to see in my data object.
This works, but is it the best way to do this?
This is the XAML:
<ItemsControl><ItemsControl.ItemTemplate><DataTemplate><Grid><TextBlock Text="{Binding Path=Data.Caption}" TextWrapping="{Binding Path=TextWrapping}"/></Grid></DataTemplate></ItemsControl.ItemTemplate></ItemsControl>
These are the objects I bind:
class MyDataObject : BindableObject // BindableObject implements INotifyPropertyChanged{ public string Caption { get; set; }} class VisualObject<T> : BindableObject{ public TextWrapping TextWrapping { get; set; } public T Data { get; set; } public VisualObject<T>(T data) { this.Data = data; }}
class MyDataObject : BindableObject // BindableObject implements INotifyPropertyChanged{ public string Caption { get; set; }}
class VisualObject<T> : BindableObject{ public TextWrapping TextWrapping { get; set; } public T Data { get; set; } public VisualObject<T>(T data) { this.Data = data; }}
So the basic question is, how to set the TextWrapping property on that TextBlock in the DataTemplate for all the bound items?
Amanda W...
All-Star
17241 points
1,466 Posts
06-04-2009 5:14 AM |
Hi JoostM ,
Based on your above description, you said you declare a TextWrapping property on my data object, if you TextWrapping property is a bool type in your data object. you can try to make the Textblock's TextWrapping bind to it, and you can create a converter to convert the string TextWrapping into enum TextWrapping type.
you can try to refer below code:
<TextBlock text="tttttttttttttttttttttttt" TextWrapping="{Binding Path=TextWrapping, Converter={StaticResource myConverter}}" />
public class TextWrapConvertcs: IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { string wrap; if ((bool)value) { wrap = "Wrap"; } else { wrap = "NoWrap"; } return wrap; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }
06-04-2009 8:54 AM |
Thanks for replying, Amanda.
A value converter would not work well in my case, because MyDataObject doesn't know anything about the UI. It doesn't have any idea wether TextWrapping would have a meaning at all, and if so, which value it should have. The same would be the case if I were to declare TextWrapping as a bool: the UI decides whether the displayed items should have TextWrapping on or off, the model classes don't even know they're being displayed in something.
So I'd like to not declare a TextWrapping property on MyDataObject, but instead leave the definition somewhere else where it doesn't obscure domain code. That's what I tried to achieve witht the VisualObject<T> class.
In the code behind of the XAML it goes something like this - (Based on the XAML and class definitions from my first post, but with an x:Name="MyItemsControl" for the ItemsControl in the XAML):
// list of items that will be shownprivate ObservableCollection<VisualObject<MyDataObject>> _visualObjects = new ObservableCollection<VisualObject<MyDataObject>>(); public void Bind(IEnumerable<MyDataObject> items){ _visualObjects.Clear(); foreach (var item in items) { _visualObjects.Add(new VisualObject<MyDataObject>(item)); } MyItemsControl.ItemsSource = _visualObjects; } // set the TextWrapping of all the objects in MyItemsControlpublic void SetAllTextWrapping(TextWrapping textWrapping){ foreach (var visualObject in _visualObjects) { visualObject.TextWrapping = textWrapping; }}
// list of items that will be shownprivate ObservableCollection<VisualObject<MyDataObject>> _visualObjects = new ObservableCollection<VisualObject<MyDataObject>>();
public void Bind(IEnumerable<MyDataObject> items){ _visualObjects.Clear(); foreach (var item in items) { _visualObjects.Add(new VisualObject<MyDataObject>(item)); } MyItemsControl.ItemsSource = _visualObjects; }
// set the TextWrapping of all the objects in MyItemsControlpublic void SetAllTextWrapping(TextWrapping textWrapping){ foreach (var visualObject in _visualObjects) { visualObject.TextWrapping = textWrapping; }}
So I get a list of MyDataObjects from the server and have them displayed in the MyItemsControl using the Bind method.
When the user clicks a button to collapse the panel on which MyItemsControl is located, I call SetAllTextWrapping to control the TextWrapping property of all the items in the ItemsControl and after that start an animation that collapses the panel on which MyItemsControl is located.
My doubt is this: I'm finding myself writing a lot of these SetAllPropertyName methods, which gives me a feeling this is not the "right way" to do it.
Writing value converters based on the state of the data object should work somewhat, but then I'd still have to propagate visual state information (like TextWrapping = true) through the data model, which strikes me as not the cleanest way to do it.
06-04-2009 8:58 AM |
Of course, for the SetAllTextWrapping method to work at all, the setter of VisualObject<T>.TextWrapping needs to raise a NotifyPropertyChanged event instead of just using the default setter.
06-22-2009 10:00 AM |
(bump)