【问题标题】:How to make this nested user control display an image?如何使这个嵌套的用户控件显示图像?
【发布时间】:2014-08-22 10:07:23
【问题描述】:

我创建了一个ImageButton 用户控件。我想要另一个用户控件 - TabItem - 使用 ImageButtonTabItem 不会显示图像。

我需要做什么才能让TabItem 显示ImageButton 的图像?

这是我的代码:

<!--MainPage.xaml-->
<Page
    x:Class="ButtonTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:ButtonTest"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    xmlns:buttons="using:ButtonTest" Background="Transparent">

    <StackPanel>

        <!--there is an image displayed for this-->
        <buttons:ImageButton ImageSource="overview_64.png" />

        <!--but not for this-->
        <buttons:TabItem ImageSource="overview_64.png" TabItemText="button text" />        
    </StackPanel>
</Page>

<!--ImageButton.xaml-->
<UserControl
    x:Class="ButtonTest.ImageButton"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:ButtonTest"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="100"
    d:DesignWidth="100">

    <Button Name="imgButton" Style="{StaticResource imageButton}" />

</UserControl>

public sealed partial class ImageButton : UserControl
{
    public static readonly DependencyProperty ImageProperty = 
        DependencyProperty.Register("ImageSource", typeof(string), typeof(ImageButton), null);

    public ImageButton()
    {
        this.InitializeComponent();
        this.DataContext = this;
    }

    public string ImageSource
    {
        get { return (string)GetValue(ImageProperty); }
        //set { SetValue(ImageProperty, value); }
        set { SetValue(ImageProperty, "/Resources/Images/" + value); }
    }
}

这是 TabItem.xaml,它使用 ImageButton。 TabItem 没有显示图像。我是否正确绑定了 ImageSource?

<!--TabItem.xaml-->
<UserControl x:Class="ButtonTest.TabItem"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        xmlns:btn="using:ButtonTest"
        d:DesignHeight="85" d:DesignWidth="80">

    <StackPanel Orientation="{Binding TabOrientation}">
        <!-- TabItem uses ImageButton -->
        <btn:ImageButton ImageSource="{Binding ImageSource}"  />

        <TextBlock Name="txtText" Text="{Binding TabItemText}" />
    </StackPanel>
</UserControl>

public sealed partial class TabItem : UserControl
{
    public static readonly DependencyProperty TextProperty = 
        DependencyProperty.Register("TabItemText", typeof(string), typeof(TabItem), null);
    public static readonly DependencyProperty ImageProperty = 
        DependencyProperty.Register("ImageSource", typeof(string), typeof(TabItem), null);

    public string TabItemText
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public string ImageSource
    {
        get { return (string)GetValue(ImageProperty); }
        set { SetValue(ImageProperty, "/Resources/Images/" + value); }
    }

    public TabItem()
    {
        this.InitializeComponent();

        this.DataContext = this;
    }
}

ImageButton 使用的样式在这里定义:

<!--Image Button Style is defined here-->
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:HKC.Winterfell.WP81.Resources.Styles.Buttons">

    <Style x:Key="imageButton" TargetType="Button">
        <Setter Property="MinWidth" Value="50"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Grid>
                        <Border x:Name="border" Background="Transparent" BorderBrush="Transparent" BorderThickness="2" CornerRadius="20">
                            <Grid>
                                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Width="Auto" Grid.RowSpan="2"/>
                            </Grid>
                        </Border>

                        <Image x:Name="ImgShadow" Source="/Resources/Images/shadow_64.png" Visibility="Visible" Height="67" Width="67" Margin="10,8,0,0" />
                        <Image x:Name="Img" Source="{Binding ImageSource}" Height="64" Width="64" Margin="0,0,0,0"  />
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="MouseOver"/>
                                <VisualState x:Name="Pressed">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ImgShadow">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Margin" Storyboard.TargetName="Img">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="10,8,0,0" />
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

【问题讨论】:

    标签: c# xaml windows-runtime windows-phone windows-phone-8.1


    【解决方案1】:

    我认为从控件内部更改控件的 DataContext 不是一个好主意。我已经看过几次了,它总是造成了一些问题。

    潜在问题

    我认为这就是你的问题所在。从 TabItem 的 xaml 中查看这一行:

    <btn:ImageButton ImageSource="{Binding ImageSource}"  />
    

    此绑定将 ImageButton 的 ImageSource 属性绑定到 ImageButton 的 DataContext(就像所有绑定一样 - 它们绑定到设置它们的控件的 DataContext)。但是在构造函数中,您将上下文更改为 ImageButton 本身,因此该属性基本上绑定到自身。

    轻松修复

    最简单的解决方法是更改​​其内容的 DataContext,而不是更改整个控件的 DataContext。在您的情况下,这将是 ImageButton 的 Button 元素的 DataContext。

    换句话说 - 在 ImageButton 的构造函数中更改这一行:

    this.DataContext = this;
    

    this.imgButton.DataContext = this;
    

    当然,对 TabItem 控件执行相同的操作。

    结论什么的……

    基本上,更改 DataContext 是一个坏主意(即使您按照我的建议进行更改),因此请尽量避免它。

    附:我可能会在不更改 DC 的情况下为您提供解决方案,但现在太忙了,抱歉。如果有人这样做,我会支持他们! :)

    编辑 - 额外观察(与问题无关)

    我也不认为 setter 是个好主意:

    set { SetValue(ImageProperty, "/Resources/Images/" + value); }
    

    如果您需要使用资源/图像中没有的图像,您会非常难过。此外,将属性的类型更改为 ImageSource (因为这通常用于图像源 :))或对象可能是一个好主意。在WinRT中很多东西都可以转换成ImageSource,如果是object类型的话会更灵活。

    【讨论】:

    • @DaveDev 你是什么意思?你试过我的建议并解决了吗?另外,如果您对我所说的内容有任何疑问,请询问,我会在有时间时回答。 :)
    • 你是说我应该修改 TabItem.xaml 的&lt;btn:ImageButton ImageSource="{Binding ImageSource}" /&gt;?或修改 ImageButton.xaml 的 &lt;Button /&gt; 元素?如果我将DataContext="{Binding ImageSource}" 添加到&lt;Button /&gt; 元素,它不会显示任何内容。
    • @DaveDev 我稍微修改了答案。我希望这有帮助。 :) 如果没有 - 我会再次编辑 :)
    • 宾果游戏。这个:this.imgButton.DataContext = this; 成功了。我听到您对“/Resources/Images/”点的看法。当我把这一切正确地联系在一起时,我会调查一下。
    猜你喜欢
    • 2010-12-05
    • 2011-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 2013-07-22
    相关资源
    最近更新 更多