WinUI: How to bind item template color to a collection's value and change it on item click

youki 991 Reputation points
2022-07-02T21:47:59.967+00:00

Hello,
had to change my question.
I want to bind the background of a stackpanel within a ListView's DataTemplate to a collection.
Then i want to be able to change the color by a double click.
It shall be an indicator, if it's activated or not as follows (white vertical line):

217941-image.png

Obviously i can't find the right background data type for the runtime class (unresolved type declaration; doesn't work with string) and do i have to access the item's control on a click or do i have to change the collection and reload it?

My double click:

void winrt::App1::implementation::MainPage::ListViewTest_ItemClick(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::ItemClickEventArgs const& e)  
{  
 static double DoubleClickTimeMS = GetDoubleClickTime();  
 static double LastTimeStamp = 0;  
  
 if (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() - DoubleClickTimeMS <= LastTimeStamp)  
 {  
 // On double click  
 }  
  
 LastTimeStamp = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();  
}  

For Reviewing (6.7.22):

Hey,
I've tried the following example for a converter: https://learn.microsoft.com/en-us/uwp/api/windows.ui.xaml.data.ivalueconverter?view=winrt-22621

But i get a view errors by adding it as listview ressource (local:ColorConverter) in MainPage.xaml:

217839-image.png

217830-image.png

I've also changed the property to boolean and i don't really know, if the following will work correctly for changing the value by double clicking from the click event (i couldn't really figure out where in the view models i could do it properly so i just tested it with String in a TextBlock and it's stored but can't be displayed; can't be right, it's because of the binding?!):

e.ClickedItem().as<AppProcess>().get()->Activated(true);  

I'm just using the example from Castorix (http://pastebin.fr/105048) combinded with a mainviewmodel of the bookstore example: https://learn.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/binding-property

My converter:

ColorConverter.idl

namespace App1  
{  
    runtimeclass ColorConverter : [default] Windows.UI.Xaml.Data.IValueConverter  
    {  
        ColorConverter();  
    }  
}  

ColorConverter.h

#pragma once  
#include "ColorConverter.g.h"  
  
namespace winrt::App1::implementation  
{  
    struct ColorConverter : ColorConverterT<ColorConverter>  
    {  
        ColorConverter()  = default;  
  
        winrt::Windows::Foundation::IInspectable Convert(winrt::Windows::Foundation::IInspectable const& value, winrt::Windows::UI::Xaml::Interop::TypeName const& targetType, winrt::Windows::Foundation::IInspectable const& parameter, hstring const& language);  
        winrt::Windows::Foundation::IInspectable ConvertBack(winrt::Windows::Foundation::IInspectable const& value, winrt::Windows::UI::Xaml::Interop::TypeName const& targetType, winrt::Windows::Foundation::IInspectable const& parameter, hstring const& language);  
    };  
}  
namespace winrt::App1::factory_implementation  
{  
    struct ColorConverter : ColorConverterT<ColorConverter, implementation::ColorConverter>  
    {  
    };  
}  
  

ColorConverter.cpp (I guess bool has to be edited because of IInspectable later)

#include "pch.h"  
#include "ColorConverter.h"  
#include "ColorConverter.g.cpp"  
  
using namespace winrt;  
using namespace Windows::UI::Xaml;  
  
namespace winrt::App1::implementation  
{  
 winrt::Windows::Foundation::IInspectable ColorConverter::Convert(winrt::Windows::Foundation::IInspectable const& value, winrt::Windows::UI::Xaml::Interop::TypeName const& targetType, winrt::Windows::Foundation::IInspectable const& parameter, hstring const& language)  
 {  
 if ((bool)value) { return box_value(Microsoft::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::DarkGray() }); }  
 else { return box_value(Microsoft::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Green() }); }  
 }  
 winrt::Windows::Foundation::IInspectable ColorConverter::ConvertBack(winrt::Windows::Foundation::IInspectable const& value, winrt::Windows::UI::Xaml::Interop::TypeName const& targetType, winrt::Windows::Foundation::IInspectable const& parameter, hstring const& language)  
 {  
 throw hresult_not_implemented();  
 }  
}  

Update (7.7.22):
The errors are gone, i've added the converter's header in the pch.h. (https://stackoverflow.com/questions/44031687/vc-converter-is-not-a-member-of-namespace)

Now i have a hresult error with x:bind. May be i have to use a function?!

Windows App SDK
Windows App SDK
A set of Microsoft open-source libraries, frameworks, components, and tools to be used in apps to access Windows platform functionality on many versions of Windows. Previously known as Project Reunion.
695 questions
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,443 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. youki 991 Reputation points
    2022-07-10T00:52:00.247+00:00

    OK,
    got it.

    IValueConverter doesn't seem to work with the markup extionsion x:Bind, only with Binding. I've read that i needed a bit more to implement Binding in my Model and functions are more performant. Actually, that's the only way I managed it :)

    Added to Idl file:  
      
    Microsoft.UI.Xaml.Media.Brush BoolToColor(Boolean value);  
    

    Added to DataTemplate:

    <StackPanel Width="2" Height="20" HorizontalAlignment="Left" VerticalAlignment="Center" Background="{x:Bind BoolToColor(Activated), Mode=OneWay}" ></StackPanel>  
    

    Added in my click event for updating:

    e.ClickedItem().as<AppProcess>().get()->Activated(false);  
    
    1 person found this answer helpful.
    0 comments No comments

  2. Nico Zhu (Shanghai Wicresoft Co,.Ltd.) 12,851 Reputation points
    2022-07-04T03:02:05.42+00:00

    Hello,
    Welcome to Microsoft Q&A!

    Obviously i can't find the right background data type for the runtime class

    The better way is using IValueConverter to implement color converter to generate SolidColorBrush base on binding property value for you DataTemplate. And using bool property is good practice than string property.

    For example

    public class Model : INotifyPropertyChanged  
    {  
        public string Title { get; set; }  
        private bool _isDoubleClicked;  
        public bool IsDoubleClicked  
        {  
            get  
            {  
                return _isDoubleClicked;  
            }  
            set  
            {  
                _isDoubleClicked = value;  
                OnPropertyChanged();  
            }  
        }  
      
        public event PropertyChangedEventHandler PropertyChanged;  
        private void OnPropertyChanged([CallerMemberName] string propertyName = null)  
        {  
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));  
        }  
    }  
    

    Xaml

    217200-image.png

    Update Color

     (e.ClickedItem as Model).IsDoubleClicked = true;  
    

    Thank you.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.