Melon NG
Melon NG

Reputation: 3004

How can I binding a value of the ResourceDictionary with IValueConverter in XAML directly?

I wanna bind a value inside a ResourceDictionary which is a Theme.

I followed some tutorial in https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/theming/theming

Here is the code of the ResourceDictionary named Black.xaml:

<?xml version="1.0" encoding="utf-8"?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Test.Themes.Black">
    <Color x:Key="PrimaryBackground" x:FactoryMethod="FromHex">
        <x:Arguments>
            <x:String>#101010</x:String>
        </x:Arguments>
    </Color>    
</ResourceDictionary>

Here is the code in App.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="Test.App">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Themes/Black.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

And here is the ContentView:

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:local="clr-namespace:Test.Views"
             xmlns:VM="clr-namespace:Test.ViewModels"             
             mc:Ignorable="d"             
             x:Class="Test.Views.MainView">
    <ContentView.BindingContext>
        <VM:MainViewVM></VM:MainViewVM>
    </ContentView.BindingContext>    
    <ContentView.Content>
        <Grid BackgroundColor="">            
        </Grid>
    </ContentView.Content>
</ContentView>

Now I want to bind the BackgroundColor property of the Grid above to the value PrimaryBackground of the ResourceDictionary.

How can I achieve it? Thank you.

Upvotes: 1

Views: 816

Answers (1)

Leon Lu
Leon Lu

Reputation: 9234

Just use DynamicResource to set the BackgroundColor like following code

<Grid BackgroundColor="{DynamicResource PrimaryBackground}">
            <Label Text="Face-Palm Monkey"
                   VerticalOptions="Center"
                   Margin="15"/>

</Grid>

Here is running sceenshot.

enter image description here

I recommand you set the ResourceDictionary directly in App.xaml like following format.

<Application xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="MVVMWebView.App">
    <Application.Resources>
        <ResourceDictionary>
            <Color x:Key="PrimaryBackground" x:FactoryMethod="FromHex">
                <x:Arguments>
                    <x:String>#101010</x:String>
                </x:Arguments>
            </Color>

        </ResourceDictionary>
    </Application.Resources>
</Application>

If you want to use IValueConverter ,just add the Converter in the ContentPage.Resources like follow code. IValueConverter used Converter tab, you just use StaticResource, it does not conflict with DynamicResource

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:DataBindingDemos"
             x:Class="DataBindingDemos.EnableButtonsPage"
             Title="Enable Buttons">
    <ContentPage.Resources>
        <ResourceDictionary>
            <local:IntToBoolConverter x:Key="intToBool" />
        </ResourceDictionary>
    </ContentPage.Resources>

    <StackLayout Padding="10, 0">


        <Button Text="Search"
                HorizontalOptions="Center"
                VerticalOptions="CenterAndExpand"
                IsEnabled="{Binding Source={x:Reference entry1},
                                    Path=Text.Length,
                                    Converter={StaticResource intToBool}}" />
     </StackLayout>
   </ContentPage>

==========Update==============

I make a convert by your needs. I used Button to convert day and night. Here is running GIF.

enter image description here

 <ContentPage.Resources>
        <ResourceDictionary>
            <controls:ColorBoolConverter x:Key="intToBool" />
        </ResourceDictionary>
    </ContentPage.Resources>
    <StackLayout>

        <Button Text="Submit"
                HorizontalOptions="Center"
                VerticalOptions="CenterAndExpand"
                Command="{Binding ChangeCommand}"
                />

        <!-- Place new controls here -->
        <Grid BackgroundColor="{Binding IsDark, Converter={StaticResource intToBool}}">
            <Label Text="Face-Palm Monkey"
                       VerticalOptions="Center"
                       Margin="15"
                        />

        </Grid>
    </StackLayout>

Here is background code about the Layout.

  public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
            this.BindingContext = new MyViewModel();
        }
    }

Here is Convertor code.

    public class ColorBoolConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is bool)
            {
                if ((Boolean)value)
                    return Color.FromHex("#101010");
                else
                    return Color.White;
            }
            return Color.White;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

Here is Test MyViewModel.cs

    public class MyViewModel: INotifyPropertyChanged
    {
        public ICommand ChangeCommand { protected set; get; }
        bool _isDark = false;
        public bool IsDark
        {
            get
            {
                return _isDark;
            }

            set
            {
                if (_isDark != value)
                {
                    _isDark = value;
                    OnPropertyChanged("IsDark");

                }
            }

        }




        public MyViewModel()
        {
            ChangeCommand =  new Command(() =>
            {

                IsDark = !IsDark;


            });
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Upvotes: 4

Related Questions