Search code examples
c#xamldata-bindingwindows-runtimewindows-store-apps

Winrt, changing a color, depending on a bound value


I have a gridview that looks something like this:

<GridView ItemContainerStyle="{StaticResource GridViewItemStyle2}" ItemsSource="{Binding MyMeetingsSquareUsers}" Grid.Row="1" Margin="10,10,10,0"  SelectionMode="None" HorizontalContentAlignment="Left" VerticalContentAlignment="Bottom">
    <GridView.ItemsPanel>
        <ItemsPanelTemplate>
            <ItemsWrapGrid Orientation="Vertical" MaximumRowsOrColumns="1"/>
        </ItemsPanelTemplate>
    </GridView.ItemsPanel>
    <GridView.ItemTemplate>
        <DataTemplate>
            <Grid Height="35" Width="35" Margin="0,0,10,0" >
                <Border BorderBrush="red" BorderThickness="1" CornerRadius="15">
                    <Ellipse>
                        <Ellipse.Fill>
                            <ImageBrush Stretch="Fill" ImageSource="ms-appx:///Images/photo_empty.png"/>
                        </Ellipse.Fill>
                    </Ellipse>
                </Border>
            </Grid>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

The ItemsSource I use is a list of items of this type:

public class MeetingInvitee
{
    public string id { get; set; }
    public string status { get; set; }
    public User user { get; set; }
    public BitmapImage photo { get; set; }
}

What I would like to know is, if it is possible to change the color of the Border I use depending on the value in status

For example if I had 3 possible status: Accepted, Rejected, Pending, the colors would be set to either Green, Red or Yellow accordingly.

so if one of the items on the list had a status of Rejected the border would have a red brush


Solution

  • Conditional templates (instead of style data triggers unfortunately) are the way to go in a store app. What you need to do is define three different templates for each color and in the code behind create a template selector.

    Data Template Selector

       public class MeetingTemplateSelector : DataTemplateSelector
        {
            public DataTemplate AcceptedTemplate { get; set; }
    
            public DataTemplate RejectedTemplate { get; set; }
    
            public DataTemplate PendingTemplate { get; set; }
    
            protected override DataTemplate SelectTemplateCore(object item, 
                      DependencyObject container)
            {
               DataTemplate result;
    
               switch( ((MeetingInvitee) item).Status)
               {
                    case "Accepted" : result = AcceptedTemplate; break;
                    case "Rejected" : result = RejectedTemplate; break;
                    case "Pending"  : result = PendingTemplate; break;
               }
    
              return result;
            }
        }
    

    Declare Templates in the Resources

    <UserControl.Resources>
        <DataTemplate x:Key="AcceptedTemplate">
            <Border Background="Green">
                 ...
            </Border>
        </DataTemplate>
        <DataTemplate x:Key="RejectedTemplate">
            <Border Background="Red">
                 ...
            </Border>
        </DataTemplate>
        <DataTemplate x:Key="PendingTemplate">
            <Border Background="Yellow">
                 ...
            </Border>
        </DataTemplate>
    
        <local:MeetingTemplateSelector x:Key="meetingSelector"
                                        AcceptedTemplate="{StaticResource AcceptedTemplate}"
                                        RejectedTemplate="{StaticResource RejectedTemplate}"
                                        PendingTemplate="{StaticResource PendingTemplate}">
        </local:MeetingTemplateSelector >
    </UserControl.Resources>
    

    Usage

    <GridView ItemContainerStyle="{StaticResource GridViewItemStyle2}" 
              ItemsSource="{Binding MyMeetingsSquareUsers}" 
              ItemTemplateSelector="{StaticResource meetingSelector}">