Reputation: 1112
Context: I'm writing a UWP Twitter client.
One of the useful bits of data Twitter returns via its API are objects for content that can be linked directly in a tweet - #hashtags, @usernames, $symbols, and URLs. This makes it easy to extract these objects from the string containing a tweet's full text, in order to turn them into links.
I understand how the XAML needs to look for this, with <run>
and <hyperlink>
tags, and I've figured out how to create that XAML dynamically for each tweet object.
What I can't figure out is how to inject my generated XAML into my app's DataTemplate
. Because tweet content needs to be displayed on multiple pages in the app, I'm using a ResourceDictionary
to hold all my XAML styling, including my DataTemplate
. So, I'm entirely unsure how to connect my generated XAML to my app's UI.
For example, if a tweet looks like this:
"Hey @twitter, you're a time waster! #FridayFeeling"
My generated XAML objects look like this:
<Run>Hey </Run>
<Hyperlink link="http://twitter.com/twitter/">@twitter</Hyperlink>
<Run>, you're a time waster! </Run>
<Hyperlink link="http://twitter.com/search?hashtag=FridayFeeling">#FridayFeeling</Hyperlink>
If there's nothing to link in a tweet's text, then I can just use Tweet.Text
as-is, so I'm trying to bind this to a TextBox
. How can I handle inserting this XAML dynamically?
Am I stuck abandoning data binding entirely and looping through my collection to programmatically add all my XAML?
Here's my DataTemplate:
<DataTemplate x:Key="TweetTemplate" x:DataType="tweeter:Tweet2">
<Grid Style="{StaticResource ListItemStyle}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="30"/>
<RowDefinition Height="*"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" x:Name="RetweetedBy" x:Load="{x:Bind IsRetweet}" Height="28">
<StackPanel Orientation="Horizontal" Padding="4 8 4 0">
<StackPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="12"/>
<Setter Property="Foreground" Value="{ThemeResource SystemControlPageTextBaseMediumBrush}" />
</Style>
</StackPanel.Resources>
<Border Height="28">
<TextBlock Height="24" FontFamily="{StaticResource FontAwesome}" xml:space="preserve"><Run Text=" "/></TextBlock>
</Border>
<TextBlock Text="{x:Bind Path=User.Name}" />
<TextBlock Text=" retweeted"/>
</StackPanel>
</Grid>
<Grid Grid.Row="1">
<StackPanel Orientation="Horizontal" Padding="5">
<TextBlock Text="{x:Bind Path=Tweet.User.Name}" Margin="0 0 8 0" FontWeight="Bold" />
<TextBlock Text="{x:Bind Path=Tweet.User.ScreenName, Converter={StaticResource GetHandle}}" Foreground="{ThemeResource SystemControlPageTextBaseMediumBrush}" />
<TextBlock Text="⦁" Margin="8 0" />
<TextBlock Text="{x:Bind Path=Tweet.CreationDate, Converter={StaticResource FormatDate}}" />
</StackPanel>
</Grid>
<Grid Grid.Row="2">
<TextBlock Text="***this is where I'm having problems***" Padding="5" TextWrapping="WrapWholeWords"/>
</Grid>
<Grid Grid.Row="3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2.5*" MaxWidth="100"/>
<ColumnDefinition Width="2.5*"/>
<ColumnDefinition Width="2.5*"/>
<ColumnDefinition Width="2.5*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Button x:Name="cmdComment" Content="" Style="{StaticResource MetaButtons}" />
</Grid>
<Grid Grid.Column="1">
<Button x:Name="cmdRetweet" Content="" Style="{StaticResource MetaButtons}" />
</Grid>
<Grid Grid.Column="2">
<Button x:Name="cmdLike" Content="" Style="{StaticResource MetaButtons}" />
</Grid>
<Grid Grid.Column="3">
<Button x:Name="cmdMessage" Content="" Style="{StaticResource MetaButtons}" />
</Grid>
</Grid>
</Grid>
</DataTemplate>
Upvotes: 1
Views: 359
Reputation: 408
If you want to use attached property, here is an example to start with :
public static class Twitter
{
public static readonly DependencyProperty InlinesProperty = DependencyProperty.RegisterAttached(
"Inlines", typeof(ICollection<Inline>), typeof(Twitter), new PropertyMetadata(default(ICollection<Inline>), PropertyChangedCallback));
private static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is TextBlock tb)) return;
tb.Inlines.Clear();
if (!(e.NewValue is ICollection<Inline> inlines)) return;
foreach (var inline in inlines)
{
tb.Inlines.Add(inline);
}
}
public static void SetInlines(DependencyObject element, ICollection<Inline> value)
{
element.SetValue(InlinesProperty, value);
}
public static ICollection<Inline> GetInlines(DependencyObject element)
{
return (ICollection<Inline>) element.GetValue(InlinesProperty);
}
}
And in xaml :
<TextBlock local:Twitter.Inlines ="{x:Bind TwitterData}"></TextBlock>
Where TwitterData is a List<Inline>
Upvotes: 2