Xamarin Forms Bind Bool на основе нескольких значений - PullRequest
0 голосов
/ 22 марта 2019

Я установил флажки в своем приложении Xamarin Forms, используя следующую статью:

https://alexdunn.org/2018/04/10/xamarin-tip-build-your-own-checkbox-in-xamarin-forms/

Я пытаюсь использовать новый BindableLayout для создания списка заголовков (Mr, Mrs и т. Д.):

<StackLayout x:Name="parent"
         Grid.Row="0"
         Grid.ColumnSpan="2"
         Orientation="Horizontal"
         BindableLayout.ItemsSource="{Binding Titles}">
<BindableLayout.ItemTemplate>
    <DataTemplate>
        <StackLayout Orientation="Horizontal">
            <control:CheckBoxView VerticalOptions="CenterAndExpand"
                                  IsChecked="..."
                                  CheckedCommand="{Binding BindingContext.CheckCommand, Source={x:Reference parent}}"
                                  CheckedCommandParameter="{Binding Identifier}"
                                  HorizontalOptions="Start"
                                  OutlineColor="{Binding BindingContext.Campaign.CampaignProfile.EntryBackgroundColor, Source={x:Reference parent}}"
                                  CheckedOutlineColor="{Binding BindingContext.Campaign.CampaignProfile.EntryTextColor, Source={x:Reference parent}}"
                                  CheckColor="{Binding BindingContext.Campaign.CampaignProfile.EntryTextColor, Source={x:Reference parent}}">
            </control:CheckBoxView>
            <Label Margin="0, 0, 20, 0"
                   VerticalOptions="Center"
                   VerticalTextAlignment="Center"
                   HorizontalTextAlignment="Start"
                   HorizontalOptions="FillAndExpand"
                   TextColor="{Binding BindingContext.Campaign.CampaignProfile.TextColor, Source={x:Reference parent}}"
                   FontSize="{Binding BindingContext.Campaign.CampaignProfile.TextSize, Source={x:Reference parent}}"
                   WidthRequest="150"
                   MinimumWidthRequest="100"
                   Text="{Binding Identifier}" />
            </StackLayout>
    </DataTemplate>
</BindableLayout.ItemTemplate>

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

В CheckCommand я установил свойство (SelectedTitle) в Идентификатор набора в CheckedCommandParameter - работает нормально, однако мне нужен какой-то способ сравнить значения Identifier и SelectedTitle.

Я пытался заставить это работать, используя IValueConverter, однако я не могу привязать значение к CommandParameter, я также попробовал DataTriggers, однако это тоже не сработало.

Обновление:

Это с DataTriggers - похоже, что CheckBoxView не устанавливает свойство IsChecked

<control:CheckBoxView VerticalOptions="CenterAndExpand"
                  IsChecked="False"
                  CheckedCommand="{Binding BindingContext.CheckCommand, Source={x:Reference parent}}"
                  CheckedCommandParameter="{Binding Identifier}"
                  HorizontalOptions="Start"
                  OutlineColor="{Binding BindingContext.Campaign.CampaignProfile.EntryBackgroundColor, Source={x:Reference parent}}"
                  CheckedOutlineColor="{Binding BindingContext.Campaign.CampaignProfile.EntryTextColor, Source={x:Reference parent}}"
                  CheckColor="{Binding BindingContext.Campaign.CampaignProfile.EntryTextColor, Source={x:Reference parent}}">
<control:CheckBoxView.Triggers>
    <DataTrigger TargetType="control:CheckBoxView"
                 Binding="{Binding BindingContext.SelectedTitle, Source={x:Reference parent}}"
                 Value="{Binding Identifier}">
        <Setter Property="IsChecked"
                Value="True"/>
    </DataTrigger>
</control:CheckBoxView.Triggers>

1 Ответ

0 голосов
/ 25 марта 2019

Со временем я добавлял к этому все больше и больше сложности, что обычно свидетельствует о том, что вы движетесь в неправильном направлении. В конце концов это было решено с использованием стандартного MVVM. Я добавил новый класс под названием Salutation:

public class Salutation : INotifyPropertyChanged
{
    private string identifier = null;
    private string name = null;
    private bool selected = false;

    public event PropertyChangedEventHandler PropertyChanged;

    [JsonProperty(PropertyName = "identifier", NullValueHandling = NullValueHandling.Ignore)]
    public string Identifier
    {
        get
        {
            return identifier
        }

        set
        {
            identifier = value;
            OnPropertyChanged();
        }
    }

    [JsonProperty(PropertyName = "name", NullValueHandling = NullValueHandling.Ignore)]
    public string Name
    {
        get
        {
            return name;
        }

        set
        {
            name = value;
            OnPropertyChanged();
        }
    }

    [JsonProperty(PropertyName = "selected", NullValueHandling = NullValueHandling.Ignore)]
    public bool Selected
    {
        get
        {
            return selected;
        }
        set
        {
            selected = value;
            OnPropertyChanged();
        }
    }

    public override int GetHashCode() => (Identifier).GetHashCode();

    public bool Equals(Salutation other) => (Identifier) == (other?.Identifier);

    public override string ToString()
    {
        return Identifier;
    }

    public override bool Equals(object obj)
    {
        if (!(obj is Salutation item))
        {
            return false;
        }

        return Equals(item);
    }

    public static bool operator ==(Salutation salutation1, Salutation salutation2)
    {
        if (ReferenceEquals(salutation1, salutation2))
        {
            return true;
        }

        if (ReferenceEquals(salutation1, null) || ReferenceEquals(salutation2, null))
        {
            return false;
        }

        return salutation1.Equals(salutation2);
    }

    public static bool operator !=(Salutation salutation1, Salutation salutation2)
    {
        return !(salutation1 == salutation2);
    }

    protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null) => 
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

Затем я добавил несколько обработчиков событий, измененных для свойств и коллекций:

Titles = new ObservableRangeCollection<Models.Salutation>();
Titles.CollectionChanged += Titles_CollectionChanged;
private bool handleEvent = true;

private void Titles_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    if (e.NewItems != null)
        foreach (Models.Salutation item in e.NewItems)
            item.PropertyChanged += Salutation_PropertyChanged;

    if (e.OldItems != null)
        foreach (Models.Salutation item in e.OldItems)
            item.PropertyChanged -= Salutation_PropertyChanged;
}

private void Salutation_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if(!handleEvent)
    {
        return;
    }

    if (e.PropertyName == "Selected")
    {
        handleEvent = false;

        if (sender is Models.Salutation selectedSalutation)
        {
            if (selectedSalutation.Selected)
            {
                Reset(sender as Models.Salutation);
            }
        }

        handleEvent = true;
    }
}

XAML:

<control:CheckBoxView VerticalOptions="CenterAndExpand"
                      IsChecked="{Binding Selected, Mode=TwoWay}"
                      HorizontalOptions="Start"
                      OutlineColor="{Binding BindingContext.Campaign.CampaignProfile.EntryBackgroundColor, Source={x:Reference parent}}"
                      CheckedOutlineColor="{Binding BindingContext.Campaign.CampaignProfile.EntryTextColor, Source={x:Reference parent}}"
                      CheckColor="{Binding BindingContext.Campaign.CampaignProfile.EntryTextColor, Source={x:Reference parent}}">
</control:CheckBoxView>

Намного проще!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...