Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
662 views
in Technique[技术] by (71.8m points)

xaml - Binding the Content property of a ContentControl in WinRT

Let's say I have a Windows Store app (targeting Windows 8.1), and on a page there's a ContentControl that looks like this:

<ContentControl>
  <ContentControl.Content>
    <TextBlock>Hello world</TextBlock>
  </ContentControl.Content>
</ContentControl>

This works absolutely fine, but if I try to set the content up as a resource, like this:

<Page.Resources>
  <TextBlock x:Key="TestContent">Hello world</TextBlock>
</Page.Resources>
<ContentControl Content="{StaticResource TestContent}" />

Everything looks great in the designer, but I get the following error at runtime:

Failed to assign to property 'Windows.UI.Xaml.Controls.ContentControl.Content'

I've tried defining the resource in various places (app.xaml, separate resource files, etc.) but I get the same error each time.

So, I have some questions:

  1. Should this be possible in WinRT XAML? Am I just doing something stupid?
  2. Is there another way to resource arbitrary content like this, e.g. path data? (I had some limited success by defining a style for a Path element, configuring the path data in a setter, but it doesn't seem to re-bind when navigating back to a page. That's a whole other issue though...)
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Normally, a resource is a shared "single instance" and various XAML elements are referring to the single shared instance. I'm not sure why the Designer implies this would work (other than its heritage in supporting multiple types of "XAML"). In the case of a TextBlock though, it's a bit different as you'd want the Element instance to be able to be replicated and instantiated multiple times (potentially being hosted in multiple ContentControls for example).

WPF had a feature to make this work, in a a special attribute called x:Shared. You'd set that to false to indicate that a Resource was not shared and that each request for the resource should return a new instance. WinRT does not have this same feature.

There is a fully supported work-around however that you might consider.

One option would be to use a Template instead of replacing the content directly as you have tried:

<Page.Resources>
    <Style x:Name="replacement" TargetType="ContentControl">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ContentControl">
                    <TextBlock FontSize="100" Foreground="Red">Hello!</TextBlock>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <ContentControl Style="{StaticResource replacement}"></ContentControl>
</Grid>

Syntactically, it's a little longer of course, but functionally, it should be the same results.

Without the x:Shared, you are limited to being able to bind to resources that are the intrinsic data types, such as x:string (as the example below works):

<Page.Resources>
    <x:String x:Key="tbResource">The Text!</x:String>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" >
    <ContentControl Content="{StaticResource tbResource}" ></ContentControl>
</Grid>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...