Конвертер непрозрачности Xamarin MVVM?

Итак, у меня есть пять изображений, когда вы нажимаете на одно из них, я хочу, чтобы одно из них получило полную непрозрачность, а другое - только половину, чтобы показать, что оно выбрано.

Мне удалось сделать это с помощью этого метода, однако это не сработает, поскольку мне не разрешено ссылаться на представление в MVVM.

Я подумал, что мне придется использовать конвертеры для непрозрачности и отправлять изображение в качестве параметра команды? Раньше я использовал конвертеры, но никогда не делал свои собственные, поэтому я не знаю, что делать, впервые пытаясь использовать Mvvm.

   public void OnStatusTapped(object sender, EventArgs args)
        {
            statusUnResolved.Opacity = 0.5;
            statusInProgress.Opacity = 0.5;
            statusDone.Opacity = 0.5;

            var image = (Image)sender;
            image.Opacity = 1;

            String[] buttons = new String[StatusValues.Count];
            for (int n = 0; n < StatusValues.Count; ++n)
            {
                buttons[n] = StatusValues[n].Name;
            }
            if (image.Source is FileImageSource)
            {
                FileImageSource fileImageSource = (FileImageSource)image.Source;
                string fileName = fileImageSource.File;
                foreach (var item in StatusValues)
                {
                    if (item.Name == fileName)
                    {
                        Issue.StatusEx = item.Value;
                        StatusChecker();
                        return;
                    }
                }
            }
        }



 private readonly ICommand onStatusTappedCommand = null;
public ICommand OnStatusTappedCommand
{
    get { return onStatusTappedCommand ?? new Command(OnStatusTapped); }
}


            <StackLayout Grid.Row="3" Grid.Column="1" Orientation="Horizontal" Spacing="0"  >
                <Image x:Name="statusUnResolved" Source="statusUnresolved.png" HorizontalOptions="Center" VerticalOptions="Center" HeightRequest="40" Opacity="0.6">
                    <Image.GestureRecognizers>
                        <TapGestureRecognizer Tapped="OnStatusTapped" NumberOfTapsRequired="1"/>
                    </Image.GestureRecognizers>
                </Image>
            </StackLayout>
            <StackLayout Grid.Row="3" Grid.Column="2" Orientation="Horizontal" Spacing="4">
                <Image x:Name="statusInProgress" Source="statusInProgress.png" HorizontalOptions="Center" VerticalOptions="Center" HeightRequest="40" Opacity="0.6" >
                    <Image.GestureRecognizers>
                        <TapGestureRecognizer Tapped="OnStatusTapped" NumberOfTapsRequired="1"/>
                    </Image.GestureRecognizers>
                </Image>
            </StackLayout>
            <StackLayout Grid.Row="3" Grid.Column="3" Orientation="Horizontal" Spacing="4" >
                <Image x:Name="statusDone" Source="statusDone.png" HorizontalOptions="Center" VerticalOptions="Center" HeightRequest="40" Opacity="1">
                    <Image.GestureRecognizers>
                        <TapGestureRecognizer Tapped="OnStatusTapped" NumberOfTapsRequired="1"/>
                    </Image.GestureRecognizers>
                </Image>
            </StackLayout>
        </Grid>

person JsonDork    schedule 05.03.2018    source источник


Ответы (1)


Предполагая, что у вас всегда будут эти 5 определенных изображений на экране, вы можете создать пять свойств double в своей ViewModel (по одному для каждого изображения), то есть:

public double StatusUnresolvedOpacity
{
    get => _statusUnresolvedOpacity;
    set
    {
        if (_statusUnresolvedOpacity != value)
        {
            _statusUnresolvedOpacity = value;
            OnPropertyChanged(nameof(StatusUnresolvedOpacity));
        }
    }
}

А также есть еще один метод, который может сбросить непрозрачность каждого до 0,5, т.е.

public void ResetOpacities()
{
    StatusUnresolvedOpacity = 0.5;
    StatusInProgressOpacity = 0.5;
    ...
}

А затем дайте каждому изображению распознаватель жестов касания, который вызовет ResetOpacities(), а затем напрямую установите свойство View Model кнопки, на которую нажали, на 1.0. то есть:

private void OnStatusUnresolvedTapped(object sender, EventArgs e)
{
    myViewModel.ResetOpacities();
    myViewModel.StatusUnresolvedOpacity = 1.0;
}

Если вы действительно хотите использовать преобразователь значений, я бы вместо этого предложил создать пять свойств bool вместо свойств double, то есть:

public bool IsStatusUnresolvedActive { get ... set ... }

И теперь вместо того, чтобы сбрасывать/устанавливать непрозрачность, вы можете просто установить свойство активной кнопки в true, а неактивной - в false. Затем в вашем преобразователе значений:

public class ActiveOpacityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (bool)value ? 1.0 : 0.5;
    }

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

И использовать в вашем xaml:

<ContentPage x:converters="clr-namespace:MyProject.WhateverFolderValueConverersAreIn;assembly:MyProject" />
    <ContentPage.Resources>
        <ResourceDictionary>
            <converters:ActiveOpacityConverter x:Key="activeOpacityConverter" />
        </ResourceDictionary>
    </ContentPage.Resources>
    <Image Opacity={Binding IsStatusUnresolvedActive, 
                            Converter={converters:activeOpacityConverter}}
</ContentPage>
person sme    schedule 05.03.2018
comment
Спасибо, отличное объяснение. Не уверен, буду ли я использовать конвертер или первый упомянутый вами метод, но попробую оба и почувствую, какой из них лучше. Спасибо - person JsonDork; 05.03.2018