Silverlight 4 RichTextBox Bind Data using DataContext - silverlight

I am working with Silverlight 4 and trying to put my test apps multilingual but I am having some trouble when I arrive to the "RichTextBox" control. I am able to bind it properly by doing back-code (c#), but when trying using the "DataContext" attributes I am not able to load it at all.
I have created a FormatConverter that return a Block (paragraph) for testing and my code where I have my RichTextBox looks like:
<RichTextBox x:Name="rtaTest" BorderThickness="0" IsReadOnly="True" UseLayoutRounding="True"
DataContext="{Binding Source={StaticResource Localization}, Path=Home.MainContent, Converter={StaticResource ParagraphFormatConverter}}">
</RichTextBox>
I am wondering if there is a way of binding a RichTextBox from the XAML.

Run seems to support databinding in SL4, as in:
<RichTextBox>
<Paragraph>
<Run Text="{Binding Path=LineFormatted}" />
</Paragraph>
</RichTextBox>

I think you may be a little confused about the used of the DataContext. You might for example have some Rich text where some children of one or more InlineUIContainer elements may retrieve their text from a property of some object. You would assign the object to the DataContext.
Whilst I'm not quite sure what you were expecting to achieve but I suspect that what you really need is for your converter to actually return a BlocksCollection (even if it just contains the single Block you were originaly returning) and then to bind as:-
<RichTextArea x:Name="rtaTest" BorderThickness="0" IsReadOnly="True"
UseLayoutRounding="True"
Blocks="{Binding Source={StaticResource Localization},
Path=Home.MainContent, Converter={StaticResource ParagraphFormatConverter}}" />

This FillFromXml is a WPF thing? Don't see it in Silverlight.

Blocks cannot be set, they can only be fetched. One way to set the blocks for a RichTextArea is
public static void UpdateRichTextArea(RichTextArea area, string xmlText)
{
if (area == null)
return;
area.Blocks.FillFromXml(xmlText, true);
}

Related

Can I bind to an ancestor DataTemplate in Silverlight?

I'm having trouble pulling off a binding that I believe should be valid in Silverlight 5:
<Controls:GraphLayout>
<Controls:GraphLayout.VertexTemplate>
<DataTemplate>
<TextBox ... />
</DataTemplate>
</Controls:GraphLayout.VertexTemplate>
<Controls:GraphLayout.SubgraphTemplate>
<DataTemplate>
<Controls:GraphLayout VertexTemplate="{Binding VertexTemplate, RelativeSource={RelativeSource AncestorType=Controls:GraphLayout}}"/>
</DataTemplate>
</Controls:GraphLayout.SubgraphTemplate>
</Controls:GraphLayout>
This is a simplified example but hopefully it's pretty readable. In excessence I'm trying to bind the VertexTemplate of the SubgraphTemplate to the VertexTemplate of the containing control (the root GraphLayout control). Unfortunately, in the code behind I can see that VertexTemplate is null in the subgraph control.
May be your code can work (this is strange that you bound to something that doesn't have an x:Key and I think you should use {StaticResource SomethingWithName})).
But actually what you looking for is DataTemplateSelector. It's very easy to use and actually support the logic you described.

DataBinding to a List in silverlight

I've got a Grid which contains a TextBlock. The Grid's DataContext is of type List<MyClass>, and I'd like to bind the TextBlock.Text property to the MyClass.MyProperty property of first element in the List. I tried something like:
<Grid x:Name="RootLayout">
<TextBlock Text="{Binding [0].MyProperty}" />
</Grid>
But of course, that did not work. What's the right way of doing this?
Edit:
I'm going to try and make my explanation more clear. I've got multiple elements in the grid, each of which binds to a different item in the list. The items are laid out in a customized manner which cannot be accomplished by a GridView or ListBox. One of the items in the Grid is the TextBlock, and I'd like to bind its Text property to a property of the first element in the list. Once I know how to do that, I can extend that knowledge to add bindings to the rest of the elements in the grid.
Edit 2:
Turns out, my code works just fine in Silverlight. My project is actually a WinRT project, but I figured I'd get quicker answers if I tagged it as Silverlight, since databinding is supposed to work the same. I'm assuming this is a bug in WinRT, so I'll just have to find a workaround for it :(
I'm not sure I get why you want to do this, but you could create a property that returns what you want from the item in the list like so:
public string MyBindingProperty
{
get { return MyList != null && MyList.Count > 0 ? MyList[0].MyProperty : "Error Text"; }
}
Then you'd bind to MyBindingProperty:
<TextBlock Text="{Binding MyBindingProperty}" />
EDIT
I was wrong in saying you can't get at the items in the List - my bad. Your binding should look like this:
<TextBlock Text="{Binding [0].MyProperty}" />
If you need me I'll be in the corner enjoying my humble pie.
I am not an expert of SL but I think your are using the wrong Grid object; try with DataGrid in this way:
<data:DataGrid x:Name="targetDataGrid">
<data:DataGrid.Columns>
<data:DataGridTextColumn Header="MyProperty"
Binding="{Binding MyProperty}" />
</data:DataGrid.Columns>
</data:DataGrid>
also see here for more details: Defining Silverlight DataGrid Columns at Runtime
Edit: then go this way:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding MyProperty}" />
</Grid>
found here: http://msdn.microsoft.com/en-us/library/cc278072%28v=VS.95%29.aspx scroll donw the article...

MVVM WPF databinding to a Skype-like chat?

Hey guys, I've got what I think is an interesting question:
You all know and love the Skype chat interface: each message is enclosed in a bubble, with emoticons and link capabilities, as well as an avatar at the left.
What is the most ideal WPF component to house each message in, if I were creating a Skype-like interface?
I am using MVVM, so all my messages are stored in the ViewModel as an ObservableCollection.
I have had problems binding to a RichTextBox, and so I have investigated binding to a Listbox, where each list item is a message and each item is styled to have a Skypey border and avatar etc.
Any ideas?
The only suitable solution that I have found is using the flowdocumentreader and an ivalueconverter to convert an array of strings to a flowdocument. It actually works great once I made my own scripting language similar to bbcode.
This was the sample I learned from. http://michaelsync.net/2009/06/09/bindable-wpf-richtext-editor-with-xamlhtml-convertor
It was a little overkill for me so I ended up just making the ivalueconverter and a simple script language.
The solution i see is that you should use DataTemplate and Style. The idea is following: each text message represented by class object. Now when you bind your message inside template, you explicit tell how do you want your messages will look like.
It will better for you to create a usercontrol that will know how represent your messages.
Example that represent similar idea, but idea is the same:
<Window.Resources>
<DataTemplate DataType="{x:Type model:MessageModel}">
<ed:Callout AnchorPoint="0,1.5" Margin="10" CalloutStyle="RoundedRectangle" Content="{Binding Path=Text}" Fill="#FFF4F4F5" FontSize="14.667" HorizontalAlignment="Left" Height="100" Stroke="Black" VerticalAlignment="Top" Width="200" />
</DataTemplate>
</Window.Resources>
<Grid>
<ItemsControl ItemsSource="{Binding Path=MsgList}" />
</Grid>
For that example you need attach Microsoft.Expression.Drawing.sll which come aside with Blend 4.

WPF: How to embed button inside text flow (wrap text around button)?

I'd like an advice to the following problem: I want to embed a Button into a text flow, but when I embed a Button and Label (or TextBlock) into the WrapPanel, I get the first figure:
alt text http://sklad.tomaskafka.com/files/wpf-wrappanel-problem.png
I think that one of solutions could be FlowDocument, but I feel that this is far too heavy for a control simple like this (which could be used in several hundred instances). Do you have some other ideas about how to implement this? Thank you!
EDIT:
One solution could be the following (I didn't know it was possible to put more stuff into TextBlock), but I would lose the ability to bind (which I need):
<TextBlock TextWrapping="Wrap">
<Span>
<Button x:Name="MyButton" Command="{Binding Path=MyCommand}" Content="+" />
<Run x:Name="MyLabel" Text="{Binding Path=Subject}" />
<!--
Problem: binding makes following error:
A 'Binding' cannot be set on the 'Text' property of type 'Run'.
A 'Binding' can only be set on a DependencyProperty of a DependencyObject.
-->
</Span>
</TextBlock>
To bind to Run.Text, checkout the BindableRun class by Fortes. Simple to implement, I use it all over my projects.
I found that implementing BindableRun correctly is pretty tricky - and almost all other available implementations will cause an exception from wpf layouting engine when the bound content changes from null to something non-null - see this problem, keyword "Collection was modified; enumeration operation may not execute."
Corrrect implementation from Microsoft is here - it shows how tricky this really is.
Solution: BindableRun class + the following markup:
<TextBlock>
<Button x:Name="MyButton" Command="{Binding Path=MyCommand}" Content="+" />
<common:BindableRun x:Name="Subject" BindableText="{Binding Path=Subject}"/>
</TextBlock>
Funny thing it works on the designer of a UserControl...
In that case, using the Property Change of your control to set the value to the Run is enough. I mean, if you had something like:
<TextBlock>
<Run Text="{Binding ElementName=thisCtrl, Path=Description}" />
</TextBlock>
Then just name the run, and on your property change handler of your UserControl DependencyProperty get/set the value.

WPF Creating a ControlTemplate that is DataBound

I have a control bound to an Object and all is well but I want to turn it into a control template bound to different objects of a similar type. I would like to do this exclusively in xaml, if possible. Any good tutorials that outline the steps?
<TextBlock Text="{Binding Source={StaticResource BorderControl}, Path=ControlName}"/>
EDIT: With a little more experience, it turns out what I need is the ability to Set the Binding source based on a property of the control. i.e.
<TextBlock Text="{Binding Source={StaticResource {TemplateBinding Tag}}, Path=ControlName}"/>
The control exists within a ControlTemplate but works correctly if I bind it directly to the data -- if that makes a difference. I don't know if this is possible or if it's the correct approach. Any thoughts welcome!
EDIT:
This doesn't work either.
<TextBlock Text="{Binding Source={TemplateBinding Tag}, Path=ControlName}"/>
I think you want ContentPresenter here (http://msdn.microsoft.com/en-us/library/system.windows.controls.contentpresenter.aspx) - think of it as one line of an ItemsControl, it's got a content and a reference to a template that will represent that content.

Resources