【问题标题】:Access and modify child items of Button in UWP C++/CX app at runtime在运行时访问和修改 UWP C++/CX 应用中 Button 的子项
【发布时间】:2017-09-21 05:09:07
【问题描述】:

我对 UWP Xaml C++/CX 开发还很陌生,所以如果我使用了错误的术语,我深表歉意。

我正在尝试制作图像/照片缩略图选择托盘。用户将选择要浏览的文件夹,内容将显示在可滚动的缩略图托盘中,文件名显示在下方。

页面是在 xaml 中构建的,我使用的是 C++/CX。缩略图托盘是使用以下 xaml 构建的

<ScrollViewer Grid.Row="1" Margin="20,20,20,20" ScrollViewer.VerticalScrollBarVisibility="Hidden">
        <Grid x:Name="thumb_grid">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>

            </Grid.RowDefinitions>
        </Grid>
</ScrollViewer>

我使用

通过代码动态添加新行
AddRow() {
   RowDefinition^ rd = ref new RowDefinition();
   rd->Height.Auto;
   thumb_grid->RowDefinitions->Append(rd);
}

然后我用一个新的 Button 填充每个网格元素

AddImageButton(int row, int col) {
   Button^ b = ref new Button();

   auto style = R->Lookup("ButtonStyle1");
   b->Style = safe_cast<Windows::UI::Xaml::Style^>(style);

   thumb_grid->Children->Append(b);
   thumb_grid->SetRow(b, row);
   thumb_grid->SetColumn(b, col);
}

“ButtonStyle1”在我的 dictionary.xaml 中定义为

   <Style x:Key="ButtonStyle1" TargetType="Button">

    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}"/>
    <Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundTransparentBrush}"/>
    <Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}"/>
    <Setter Property="Padding" Value="8,4,8,4"/>
    <Setter Property="Margin" Value="10"/>
    <Setter Property="HorizontalAlignment" Value="Stretch"/>
    <Setter Property="VerticalAlignment" Value="Stretch"/>
    <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
    <Setter Property="FontWeight" Value="Normal"/>
    <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
    <Setter Property="UseSystemFocusVisuals" Value="True"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="*"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>

                    <VisualStateManager.VisualStateGroups>

                    <!--REMOVED THIS SECTION TO REDUCE EXAMPLE CODE-->

                    </VisualStateManager.VisualStateGroups>
                    <ContentPresenter x:Name="ContentPresenter" AutomationProperties.AccessibilityView="Raw" 
                                      BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" 
                                      ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" 
                                      Content="{TemplateBinding Content}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                      Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>

                    <Image x:Name="thumb_image" Grid.Row="0" HorizontalAlignment="Stretch" Source="Assets/demo.jpg"/>

                    <TextBlock x:Name="thumb_filename" Grid.Row="1" Text="demo.jpg" FontSize="20" Foreground="White"
                            HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                            TextAlignment="Center"/>

                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

所有这些都会导致创建所需的输出,如下图所示。显然,我目前只是为 Button 内容使用硬编码的图像和文本。

问题
问题是如何动态更改自定义图片按钮的内容?

目前我可以通过按名称访问内容来更改按钮内的图像。但是,这要求按钮的图像内容具有唯一的名称。

Xaml 代码

<Button x:Name="btnToggleShowHide" Grid.Row="1"  Height="50" Width="50" 
            HorizontalAlignment="Left" VerticalAlignment="Bottom" 
            Background="Transparent"
            Click="btnToggleShowHide_Click">
    <Image x:Name="imgToggleShowHideBtn"  
        Source="Assets/Graphics/show.png"
        HorizontalAlignment="Stretch" 
        VerticalAlignment="Stretch"/>
</Button>

以及更改图像的C++/CX代码(不包括实际逻辑,仅显示使用的代码)

show = ref new BitmapImage(ref new Uri(imgToggleShowHideBtn->BaseUri->RawUri, "Assets/Graphics/show.png"));
hide = ref new BitmapImage(ref new Uri(imgToggleShowHideBtn->BaseUri->RawUri, "Assets/Graphics/hide.png"));

imgToggleShowHideBtn->Source = show;
imgToggleShowHideBtn->Source = hide;

但我无法通过使用其名称直接访问自定义按钮图像“demo.jpg”中的文本

thumb_filename->Text = "test.jpg";

因为文本块 thumb_filename 仅在运行时存在。在 AddImageButton() 我需要以某种方式设置内容,但无法弄清楚如何访问按钮中的子对象。在我看来,我想做类似的事情

Button^ b = ref new Button();
auto style = R->Lookup("ButtonStyle1");
b->Style = safe_cast<Windows::UI::Xaml::Style^>(style);

//NOT ACTUAL CODE - THIS IS WHAT I'M TRYIN TO ACHIEVE
b->Image->Source = img;        //obviously wont work because it has no knowledge whether ButtonStyle1 contains an image
b->TextBlock->Text = filename; //obviously wont work because it has no knowledge whether ButtonStyle1 contains a textblock

【问题讨论】:

  • 我建议您可以将自定义按钮替换为 GridView 。您可以通过修改ViewModel 来动态更改GridView 的内容。
  • 谢谢,我将使用 GridView 进行调查。你有什么好的参考例子吗?
  • 当然,你可以参考这个official code sample。请检查。
  • 谢谢,我已经下载了所有这些,并且一直在使用它们来学习。唯一的问题是缺乏基于 C++ 的示例。

标签: xaml uwp uwp-xaml c++-cx


【解决方案1】:

所以我最终使用了Nico Zhu - MSFT 建议的方法,并将 GridView 与数据绑定一起使用。

首先我创建了一个按钮类(注意:我还在完善中,所以可能会有一些多余的sn-ps)

namespace Models {

    [Windows::UI::Xaml::Data::Bindable]
    public ref class FileBrowser sealed
    {

    private:
        Platform::String^ _fname;
        Platform::String^ _path;
        ImageSource^ _thumbImage;
        BitmapImage^ _imagedata;

    public:
        FileBrowser();

        property Platform::String^ Filename
        {
            Platform::String^ get()
            {
                return _fname;
            }
            void set(Platform::String^ value)
            {
                _fname = value;
            }
        }

        property Platform::String^ Filepath
        {
            Platform::String^ get()
            {
                return _path;
            }
            void set(Platform::String^ value)
            {
                _path = value;
            }
        }

        property ImageSource^ ThumbImage
        {
            ImageSource^ get()
            {
                return _thumbImage;
            }
            void set(ImageSource^ value)
            {
                _thumbImage = value;
            }
        }

        property BitmapImage^ ImageData
        {
            BitmapImage^ get()
            {
                return _imagedata;
            }
            void set(BitmapImage^ value)
            {
                _imagedata = value;
            }
        }

    };
}

将#include“FileBrowser.h”添加到“MainPage.xaml.h”。在包含图像浏览器/列表的 View.xaml 页面中,将 xmlns:local="using:Models" 添加到标记中。

我的GridView是这样创建的

<GridView x:Name="thumb_grid" Grid.Row="1" Margin="20,20,20,20" IsItemClickEnabled="True" SelectionMode="Single" ItemClick="thumb_grid_ItemClick">
            <GridView.ItemTemplate>
                <DataTemplate>
                    <Grid MaxHeight="200" MinHeight="200" MinWidth="200" MaxWidth="200">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="auto"/>
                        </Grid.RowDefinitions>
                        <Image Grid.Row="0"  Source="{Binding ImageData}"/>
                        <TextBlock Text="{Binding Filename}" Grid.Row="1" FontSize="20" Foreground="Gray" VerticalAlignment="Center" HorizontalAlignment="Center"/>

                    </Grid>
                </DataTemplate>
            </GridView.ItemTemplate>
            <GridView.Items>

            </GridView.Items>
        </GridView>

在运行时,一个新按钮被添加到 GridView 中,使用(其中 f 和我提供相关文件和图像数据)

auto btn = ref new Models::FileBrowser();
btn->Filename = f->GetAt(i)->DisplayName + f->GetAt(i)->FileType;
btn->Filepath = f->GetAt(i)->Path;
btn->ImageData = I;
thumb_grid->Items->Append(btn);

这会产生显示文件夹内容的所需图像托盘。每个图像可点击/可触摸并调用相同的函数,在这种情况下,GridView 中的每个项目在按下时都会调用 thumb_grid_ItemClick()。

按钮的数据可以通过以下方式获取

void View::thumb_grid_ItemClick(Platform::Object^ sender, Windows::UI::Xaml::Controls::ItemClickEventArgs^ e)
{
    auto btn = (Models::FileBrowser^)e->ClickedItem;
}

【讨论】:

    猜你喜欢
    • 2020-06-05
    • 1970-01-01
    • 1970-01-01
    • 2013-10-19
    • 2018-02-06
    • 2019-07-18
    • 1970-01-01
    • 2019-10-02
    • 1970-01-01
    相关资源
    最近更新 更多