Skip to main content
Home Forums Silverlight Programming Programming with .NET - General Some databinding issues
5 replies. Latest Post by Yi-Lun Luo - MSFT on July 5, 2008.
(0)
davidpni
Member
66 points
82 Posts
07-02-2008 2:30 PM |
Okay, here is the deal. I have a ListBox in my XAML which uses an ItemTemplate for each item in the ListBox. It looks like the following:
<ListBox Grid.Row="1" x:Name="CommentsList"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <StackPanel Background="{Binding NoteColor}" Margin="10" Width="15" MinHeight="20"> <TextBlock Text="{Binding Number}" HorizontalAlignment="Center" FontSize="20" VerticalAlignment="Center"></TextBlock> </StackPanel> <silversdk:TextEditor Text="{Binding Text, Mode=TwoWay}" Margin="0,10,0,0" Width="150"></silversdk:TextEditor> </StackPanel> </DataTemplate> </ListBox.ItemTemplate></ListBox>
The contents of the ListBox actually get set in the C# code. It is only line of code and looks something like: CommentsList.ItemsSource = data;
Now, you will notice that in my ItemTemplate I am using a "TextEditor" UserControl which I created. The XAML is very short, and here it is:
<UserControl x:Class="SilverlightProject.TextEditor" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:SilverlightProject;assembly=SilverlightProject" Width="Auto" Height="Auto"> <Grid x:Name="LayoutRoot" Background="Transparent"> <TextBlock x:Name="StaticText" Text="{Binding Text}" MouseLeftButtonDown="TextBlock_MouseLeftButtonDown" TextWrapping="Wrap"></TextBlock> <TextBox x:Name="DynamicText" Text="{Binding Text, Mode=TwoWay}" Visibility="Collapsed" TextWrapping="Wrap"></TextBox> </Grid></UserControl>
The point of this UserControl is to allow the user to click on the "TextEditor", and when that happens the TextBlock will become collapsed and the TextBox will become visible, allowing the user to then edit the text. When the "TextEditor" UserControl loses focus, the TextBox will once again become invisible and the TextBlock will be visible. (Both things databind with the same source, as you can tell).
Here is the problem: Although the "TextEditor" control works great by itself, my application suddenly crashes when I try to use it a scenario like the one above in the ListBox. When I try to add things to the ListBox, the entire page just goes white....which I know sounds weird, but that is what happens. I am not getting any databinding errors in the output window of Visual Studio, however, so I don't know what the problem is.
Can I not do this kind of databinding? If you notice, there is also two way databinding going between the Text of the TextEditor and the Text of the data source. The hope is that when the user edits something in the TextBox, the change will be subsequently seen in the Text property of the TextEditor UserControl, and then also be passed along to the data source in the end....but like I said, it's just crashing.
Any suggestions?
Tomek Km...
356 points
69 Posts
07-02-2008 2:35 PM |
Hey,
How do you set DataContext in your TextEditor?
Regards,Tomek
07-02-2008 3:26 PM |
Like so:
public partial class TextEditor : UserControl, INotifyPropertyChanged{ TextEditorModel _text; public string Text { get { return _text.Text; } set { _text.Text = value; NotifyPropertyChanged("Text"); } } public TextEditor() { InitializeComponent(); _text = new TextEditorModel(); LayoutRoot.DataContext = _text; ...more stuff... } ....more stuff...}public class TextEditorModel{ string _text; public string Text { get { return _text; } set { _text = value; NotifyPropertyChanged("Text"); } }}
Note: I would do something like this:
public partial class TextEditor : UserControl, INotifyPropertyChanged{ string _text; public string Text { get { return _text; } set { _text = value; NotifyPropertyChanged("Text"); } } public TextEditor() { InitializeComponent(); LayoutRoot.DataContext = this; ...more stuff... } ....more stuff...}
except for the fact that: LayoutRoot.DataContext = this; causes crashes in Beta 2.
Yi-Lun L...
All-Star
25052 points
2,747 Posts
07-04-2008 3:43 AM |
Hello, only a DependencyProperty can be binding target. So you must change your Text property in the TextEditor to a DependencyProperty:
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(TextEditor), new PropertyMetadata(new PropertyChangedCallback(TextChanged)));public string Text{get { return (string)GetValue(TextProperty); }set { SetValue(TextProperty, value); }}private static void TextChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e){((TextEditor)sender)._text.Text = e.NewValue.ToString();((TextEditor)sender).NotifyPropertyChanged("Text");}
07-04-2008 9:42 PM |
No offense, but you are completely wrong in that respect. I have heard lots of talk about how dependency properties are "for databinding" but I have been working on a Silverlight project for awhile now doing ALL SORTS of databinding and not used a single dependency property. I wish people would stop talking about them because I have yet to find ANY use for them.
07-05-2008 12:37 AM |
Well, you may not be aware. But actually most built-in properties are all DependencyProperty. That's why you can use them as binding target, create animations, Setters, etc. Have a look at the way you create a binding in code:
FrameworkElement.SetBinding(DependencyProperty dp, Binding binding)
As you can see, only DependencyProperty can be used as binding targets. But the binding source can be any properties. So in your case, TextEditor.Text must be a DependencyProperty, since it's used as a binding target. But TextEditorModel.Text can be a normal CLR property, since it's only used as a binding source.
We need DependencyProperty in many scenarios because a CLR property can only have one value, while a DependencyProperty can have many values. For example, a local value, a value set by data binding, a value set by animation, etc...