Могу ли я программно установить цвет кнопки внутри Xamarin.Forms ListView? - PullRequest
0 голосов
/ 24 октября 2019

У меня есть ListView с кнопкой, определенной внутри ViewCell. Я хотел бы знать, как я могу обновить цвет этой кнопки программно.

Вот как мой ListView определен в XAML.

<ListView x:Name="HeaderListView">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <ViewCell>
                                <Grid>
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="*"/>
                                        <RowDefinition Height="*"/>
                                    </Grid.RowDefinitions>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="*"/>
                                        <ColumnDefinition Width="*"/>
                                    </Grid.ColumnDefinitions>
                                    <Label Text="{Binding Title}" TextColor="Black"/>
                                    <Button x:Name="DetailButton" Grid.Row="1"
                                            BackgroundColor="Blue"
                                            TextColor="White"
                                            Text="Details"
                                            Clicked="DetailButton_Clicked"/>
                                </Grid>
                            </ViewCell>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>

Источником данных является база данных SQLite, которую я установил в C #:

protected override void OnAppearing()
        {
            base.OnAppearing();

            using (SQLiteConnection conn = new SQLiteConnection(App.DatabaseLocation))
            {
                conn.CreateTable<Header>();
                var header = conn.Query<Header>("select * from Header");
                HeaderListView.ItemsSource = header;
            }
        }

Кнопка Detailвыбирает строку, в которой он находится, и перемещается к DetailPage, построенному с данными заголовка выбранной строки. DetailPage содержит второй ListView, это один из таблицы Detail, который связан с таблицей Header внешним ключом. Каждая строка в таблице сведений имеет свойство bool Complete. ItemsSource для ListView в DetailPage устанавливается так же, как HeaderListView.

Пример кода, отражающего то, как выглядят мои таблицы:

public class Header
    {
        public int HeaderId { get; set; } // The primary key of the Header table
        public string Code { get; set; } // Foreign key of the Detail table

        // various Header data
        public string Data1 { get; set; }
        public DateTime Data2 { get; set; }
        public int Data3 { get; set; }
    }

public class Detail
    {
        public int DetailId { get; set; } // Primary key of Detail table
        public string Code { get; set; } // Foreign key; Many Detail rows to one Header row

        // various Detail data
        public string Detail1 { get; set; }
        public int Detail2 { get; set; }
        public TimeSpan Detail3 { get; set; }
        public bool Complete { get; set; }
    }

Желаемое поведение для кнопки «Мои подробности» в HeaderListView. выглядит следующим образом:

1) BackgroundColor="Blue", когда в заголовке нет совпадающих строк сведений, поэтому нет элементов в ListP DetailPage.

2) BackgroundColor="Orange", когда заголовок имеетхотя бы одна соответствующая строка сведений (и, следовательно, хотя бы один элемент в ListPort DetailPage), а свойство any lines 'Complete имеет значение false.

3) BackgroundColor="Green"когда в DetailPage есть хотя бы одна совпадающая строка, и все его свойств 'rows' Complete установлены в true. Если существует только одна строка, соответствующая заголовку, и его свойство 'Complete равно true, то кнопка Подробно все еще остается зеленой.

Пожалуйста, не предлагайте никаких пользовательских инструментов, если нет абсолютно никакого способасделать это с помощью инструментов Xamarin по умолчанию.

Ответы [ 3 ]

1 голос
/ 24 октября 2019

В вашем xaml вы должны установить привязку к backgroundColor вашей кнопки:

<Button  BackgroundColor="{Binding btnColor}"/>

И в приведенном ниже коде установите значение btnColor в различных ситуациях в вашем header:

protected override void OnAppearing()
{
    base.OnAppearing();

    var header = conn.Query<Header>("select * from Header");

    for (int i = 0; i < header.Count; i++)
    {
        Header h = header[i];

        if (Header has no matching Detail rows)
        {
         h.btnColor = Color.Blue;
        }
        else if (your condition)
        {
            h.btnColor = Color.Orange;
        }
        else if (your condition) {
            h.btnColor = Color.Green
        }
        else
        {
            h.btnColor = defaultColor;
        }
    }

    HeaderListView.ItemsSource = header;
}

Добавьте свойство btnColor в вашу модель:

public class Header
{
    public int HeaderId { get; set; } // The primary key of the Header table
    public string Code { get; set; } // Foreign key of the Detail table

    // various Header data
     public Color btnColor { get; set; }

}
1 голос
/ 24 октября 2019

IIRC, я уже давал вам аналогичный ответ на похожий вопрос. Вы снова должны создать ViewModel внутри вашей ViewModel.

public HeaderViewModel : BindableObject {
    public Header Header { get; set; }

    private ObservableCollection<Detail> details { get; set; }
    public ObservableCollection<Detail> Details { 
        get => details;
        set {
            details = value;
            OnPropertyChanged();
            OnPropertyChanged(nameof(ButtonBackgroundColor);
        }
    }

    public Color ButtonBackgroundColor {
        get {
            if (Details.Count == 0) return Color.Blue;
            if (Details.Any(d => !d.Complete) return Color.Orange;
            return Color.Green;
        }
    }

    public HeaderViewModel(Header header) {
        this.Header = header;
        this.Details = SelectAllDetailItemsForWithThisHeaderId() //Your query that does what the name tells
    }
}

Затем в вашей основной viewmodel для каждого элемента Header создайте экземпляр HeaderViewModel, поместите их в ObservableCollection и свяжите их как ItemsSource объекта ListView. :

public class ViewModel : INotifyPropertyChanged {
    private ObservableCollection<HeaderViewModel> headers { get; set; }
    public ObservableCollection<HeaderViewModel> Headers {
        get => headers;
        set {
            headers = value;
            OnPropertyChanged();
        }
    }

    //constructor
    public ViewModel() {
        List<Header> queriedHeaders = new List<Header>();

        //please fetch data inside your viewmodel btw, currently you do it inside the view.
        using (SQLiteConnection conn = new SQLiteConnection(App.DatabaseLocation))
        {
            conn.CreateTable<Header>();
            queriedHeaders = conn.Query<Header>("select * from Header").ToList();
        }

        List<HeaderViewModel> _headers = new List<HeaderViewModel>();
        foreach(Header h in queriedHeaders) {
            var hvm = new HeaderViewModel(h);
            _headers.Add(hvm);
        }

        this.Headers = new ObservableCollection<HeaderViewModel>(_headers);
    }
}

Затем в приведенном выше примере XAML измените два тега следующим образом:

<ListView ItemsSource="{Binding Headers}">

<Button BackgroundColor="{Binding ButtonBackgroundColor}">

1 голос
/ 24 октября 2019

Вы можете использовать стили с триггерами в xaml.

У вашей модели представления могут быть геттеры, которые возвращают цвет / стиль для используемого столбца, после чего вы можете привязать к нему цвета столбца.

Или вы можете сделать это программно, назначив фоновый цвет заголовка на основе таких данных, как datagrid.columns[0].BackgroundColor = new SolidBrush("blue"); или что-то в этом роде.

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