How to bind consistant (or global) value to DataTemplate?

SmilingMoon 981 Reputation points
2021-03-19T21:04:37.14+00:00

Hello,

I display images in GridView using DataTemplate by binding object, OgFileInfo.
I like to change the Image size fast and easy.
Currently, ThumbnailWidth and ThumbnailHeight values are bound from OgFileInfo property.
However, ThumbnailWidth and ThumbnailHeight are always Identical to all items bound.
To change the ThumbnailWidth and ThumbnailHeight, I have to loop through entire list by changing the value.
=> This works but Slow and NOT efficient and cause UI issue when there are large number of items bound.

Is there a way to bind global value to the ThumbnailWidth and ThumbnailHeight like below "GlobalSizeStatic..."?
<Grid Grid.Column="0" Width="{x:Bind GlobalSizeStatic.ThumbnailWidth, Mode=OneWay}" Height="{x:Bind GlobalSizeStatic.ThumbnailHeight, Mode=OneWay}" >
Then, I can just change the two values and all photos' size changes immediately, I wish.

I couldn't find a way to bind a value other than the object defined in x:DataType.

 <GridView x:Name="gvFiles" >
                            <GridView.ItemTemplate>
                                <DataTemplate x:DataType="modelLocal:OgFileInfo">
                                    <Grid x:Name="filesView_ThumbnailItem"
                                          Tag="{x:Bind Id, Mode=OneWay}"> 
                                        <Grid>
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="auto"></ColumnDefinition>
                                                <ColumnDefinition ></ColumnDefinition>
                                            </Grid.ColumnDefinitions>
                                            <Grid.RowDefinitions>
                                                <RowDefinition></RowDefinition>
                                            </Grid.RowDefinitions>
                                            <Grid Grid.Column="0" Width="{x:Bind **ThumbnailWidth**, Mode=OneWay}" Height="{x:Bind **ThumbnailHeight**, Mode=OneWay}" >
                                                <Image x:Name="filesView_ThumbnailImg" HorizontalAlignment="Center" VerticalAlignment="Center"                                                    
                                                   Source="{x:Bind Thumbnail, Mode=OneWay}" Stretch="UniformToFill" Tag="{x:Bind Id, Mode=OneWay}"
                                                   ></Image>

                                            </Grid>
                                        </Grid>
                                    </Grid>
                                </DataTemplate>
                            </GridView.ItemTemplate>
                            <GridView.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <ItemsWrapGrid Orientation="Horizontal"/>
                                </ItemsPanelTemplate>
                            </GridView.ItemsPanel>
                        </GridView>
Universal Windows Platform (UWP)
0 comments No comments
{count} votes

Accepted answer
  1. Peter Fleischer (former MVP) 19,231 Reputation points
    2021-03-20T09:09:42.577+00:00

    Hi,
    you can use Binding to ViewModel like in following demo.

    XAML:

    <Page
        x:Class="App1.Page26"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:App1.App26"
        xmlns:modelLocal="using:App1.App26"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
      <Page.Resources>
        <local:ViewModel x:Key="vm"/>
      </Page.Resources>
      <Grid DataContext="{StaticResource vm}">
        <Grid.RowDefinitions>
          <RowDefinition/>
          <RowDefinition Height="auto"/>
        </Grid.RowDefinitions>
        <GridView ItemsSource="{Binding View}">
          <GridView.ItemTemplate>
            <DataTemplate x:DataType="modelLocal:OgFileInfo">
              <Grid>
                <Grid>
                  <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="auto"></ColumnDefinition>
                    <ColumnDefinition ></ColumnDefinition>
                  </Grid.ColumnDefinitions>
                  <Grid.RowDefinitions>
                    <RowDefinition></RowDefinition>
                  </Grid.RowDefinitions>
                  <Grid Grid.Column="0"
                        Width="{Binding ThumbnailWidth, Source={StaticResource vm}, Mode=OneWay}" 
                        Height="{Binding ThumbnailHeight, Source={StaticResource vm}, Mode=OneWay}" >
                    <Image HorizontalAlignment="Center" 
                           VerticalAlignment="Center"   
                           Source="{x:Bind Thumbnail, Mode=OneWay}" 
                           Stretch="UniformToFill" 
                           Tag="{x:Bind Id, Mode=OneWay}"></Image>
                  </Grid>
                </Grid>
              </Grid>
            </DataTemplate>
          </GridView.ItemTemplate>
          <GridView.ItemsPanel>
            <ItemsPanelTemplate>
              <ItemsWrapGrid Orientation="Horizontal"/>
            </ItemsPanelTemplate>
          </GridView.ItemsPanel>
        </GridView>
        <Button Grid.Row="1" Content="Change Size" Command="{Binding}" Margin="5"/>
      </Grid>
    </Page>
    

    ViewModel:

    Namespace App26
      Public Class ViewModel
        Implements ICommand, INotifyPropertyChanged
    
        Public Sub New()
          LoadPictures()
        End Sub
    
        Public Property View As New ObservableCollection(Of OgFileInfo)
    
        Public Property ThumbnailWidth As Double = 100
        Public Property ThumbnailHeight As Double = 100
    
        Private Async Sub LoadPictures()
          Dim pathes = New String() {"Assets\\FlagCH.png", "Assets\\FlagUK.png", "Assets\\FlagUS.png"}
          For i = 0 To pathes.Count - 1
            Dim f = Await Package.Current.InstalledLocation.GetFileAsync(pathes(i))
            Dim p = Await GetImageSourceFromStorageFile(f)
            View.Add(New OgFileInfo With {.Id = i + 1, .Thumbnail = p})
          Next
        End Sub
    
        Private Async Function GetImageSourceFromStorageFile(sf As StorageFile) As Task(Of ImageSource)
          Using randomAccessStream = Await sf.OpenAsync(FileAccessMode.Read)
            Dim result = New BitmapImage()
            Await result.SetSourceAsync(randomAccessStream)
            Return result
          End Using
        End Function
    
        Public Event CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged
    
        Public Sub Execute(parameter As Object) Implements ICommand.Execute
          If ThumbnailWidth = 100 Then
            ThumbnailWidth = 150
            ThumbnailHeight = 150
          Else
            ThumbnailWidth = 100
            ThumbnailHeight = 100
          End If
          OnPropertyChanged(NameOf(ThumbnailWidth))
          OnPropertyChanged(NameOf(ThumbnailHeight))
        End Sub
        Public Function CanExecute(parameter As Object) As Boolean Implements ICommand.CanExecute
          Return True
        End Function
    
        Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
        Friend Sub OnPropertyChanged(<CallerMemberName> Optional propName As String = "")
          RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propName))
        End Sub
      End Class
      Public Class OgFileInfo
        Public Property Id As Integer
        Public Property Thumbnail As ImageSource
      End Class
    End Namespace
    

0 additional answers

Sort by: Most helpful