Xamarin.Forms RadioButton

Автор:

learn.microsoft.com

Xamarin.Forms RadioButton – это тип кнопки, позволяющий пользователям выбирать один вариант из набора. Каждый вариант представлен одним переключателем, и в группе можно выбрать только один переключатель. По умолчанию каждая RadioButton отображает текст:

Однако на некоторых платформах RadioButton может отображать View, и на всех платформах внешний вид каждой RadioButton может быть переопределен с помощью ControlTemplate:

Элемент управления RadioButton определяет следующие свойства:

  • Content с типом object, который определяет строку или представление, отображаемое кнопкой RadioButton.
  • IsChecked с типом bool определяет, отмечена ли кнопка RadioButton. Это свойство использует двухстороннюю привязку и по умолчанию имеет значение false.
  • GroupName с типом string определяет имя, которое указывает, какие элементы управления RadioButton являются взаимоисключающими. По умолчанию это свойство имеет значение null.
  • Value с типом object определяет необязательное уникальное значение, связанное с кнопкой RadioButton.
  • BorderColor с типом Color определяет цвет обводки границы.
  • BorderWidth с типом double определяет ширину границы RadioButton.
  • CharacterSpacing с типом double определяет расстояние между символами любого отображаемого текста.
  • CornerRadius с типом int определяет радиус угла кнопки RadioButton.
  • FontAttributes с типом FontAttributes определяет стиль текста.
  • FontFamily с типом string определяет семейство шрифтов.
  • FontSize с типом double определяет размер шрифта.
  • TextColor с типом Color определяет цвет отображаемого текста.
  • TextTransform с типом TextTransform определяет обводку любого отображаемого текста.

Эти свойства поддерживаются объектами BindableProperty, и это означает, что они могут быть объектами привязки к данным и стилизованы.

Элемент управления RadioButton в Xamarin также определяет событие CheckedChanged, которое запускается при изменении свойства IsChecked в результате пользовательских или программных манипуляций. Объект CheckedChangedEventArgs, сопровождающий событие CheckedChanged, имеет единственное свойство Value типа bool. При наступлении события значение свойства CheckedChangedEventArgs.Value устанавливается в новое значение свойства IsChecked.

Управление группированием RadioButton в Xamarin может осуществляться с помощью класса RadioButtonGroup, который определяет следующие вложенные свойства:

  • GroupName c типом string, который определяет имя группы для объектов RadioButton в Layout.
  • SelectedValue с типом object, который представляет собой значение отмеченного объекта RadioButton в группе Layout. По умолчанию это присоединенное свойство использует двухстороннюю привязку.

Создание кнопок RadioButton

Внешний вид переключателя определяется типом данных, присвоенных свойству RadioButton.Content:

  • Если свойству RadioButton.Content присвоена строка, то она будет отображаться на каждой платформе, горизонтально выровненная рядом с кружком радиокнопки.
  • Если свойству RadioButton.Content присвоено значение View, то оно будет отображаться на поддерживаемых платформах (iOS, UWP), а на неподдерживаемых платформах произойдет откат к строковому представлению объекта View (Android). В обоих случаях содержимое отображается горизонтально выровненным рядом с кружком радиокнопки.
  • Когда к радиокнопке применяется шаблон ControlTemplate, свойству RadioButton.Content на всех платформах может быть назначен объект View.

Отображение содержимого на основе строк

Кнопка RadioButton отображает текст, если свойству Content присвоена строка:

<StackLayout>
   <Label Text="What's your favorite animal?" />
   <RadioButton Content="Cat" />
   <RadioButton Content="Dog" />
   <RadioButton Content="Elephant" />
   <RadioButton Content="Monkey"
                IsChecked="true" />
</StackLayout>

Отображение произвольного содержимого

В iOS и UWP кнопка RadioButton может отображать произвольное содержимое, если свойству Content присвоено значение View:

<StackLayout>
   <Label Text="What's your favorite animal?" />
   <RadioButton>
       <RadioButton.Content>
           <Image Source="cat.png" />
       </RadioButton.Content>
   </RadioButton>
   <RadioButton>
       <RadioButton.Content>
           <Image Source="dog.png" />
       </RadioButton.Content>
   </RadioButton>
   <RadioButton>
       <RadioButton.Content>
           <Image Source="elephant.png" />
       </RadioButton.Content>
   </RadioButton>
   <RadioButton>
       <RadioButton.Content>
           <Image Source="monkey.png" />
       </RadioButton.Content>
   </RadioButton>
</StackLayout>

В данном примере объекты RadioButton неявно сгруппированы внутри одного родительского контейнера. Такой XAML приводит к виду, показанному на следующих скриншотах:

В Android объекты RadioButton отображают строковое представление объекта View, заданного в качестве содержимого:

Примечание. Когда к RadioButton применяется шаблон ControlTemplate, свойству RadioButton.Content на всех платформах может быть назначен объект View.

Связывание значений с кнопками RadioButton

Каждый объект RadioButton имеет свойство Value типа object, которое определяет необязательное уникальное значение, ассоциируемое с переключателем. Это позволяет сделать значение объекта RadioButton отличным от ее содержимого и особенно полезно, когда объекты RadioButton отображают объекты View.

В следующем XAML показана установка свойств Content и Value для каждого объекта RadioButton:

<StackLayout>
   <Label Text="What's your favorite animal?" />
   <RadioButton Value="Cat">
       <RadioButton.Content>
           <Image Source="cat.png" />
       </RadioButton.Content>
   </RadioButton>
   <RadioButton Value="Dog">
       <RadioButton.Content>
           <Image Source="dog.png" />
       </RadioButton.Content>
   </RadioButton>
   <RadioButton Value="Elephant">
       <RadioButton.Content>
           <Image Source="elephant.png" />
       </RadioButton.Content>
   </RadioButton>
   <RadioButton Value="Monkey">
       <RadioButton.Content>
           <Image Source="monkey.png" />
       </RadioButton.Content>
   </RadioButton>
</StackLayout>

В этом примере каждый переключатель имеет в качестве содержимого изображение, а также определяет значение на основе строки. Это позволяет легко определить значение отмеченного переключателя.

Группирование переключателей

Кнопки-переключатели работают в группах, и существует три подхода к их группировке:

  • Поместить их в один и тот же родительский контейнер. Это называется неявной группировкой.
  • Установить одинаковое значение свойства GroupName для каждого переключателя в группе. Это называется явной группировкой.
  • Установить вложенное свойство RadioButtonGroup.GroupName родительского контейнера, которое, в свою очередь, устанавливает свойство GroupName всех объектов RadioButton в этом контейнере. Это также известно, как явная группировка.

Важно. Объекты RadioButton не обязательно должны принадлежать одному родителю, чтобы быть сгруппированными. Они являются взаимоисключающими при условии, что у них есть общее имя группы.

Явная группировка с помощью свойства GroupName

В следующем примере XAML показана явная группировка объектов RadioButton путем установки их свойств GroupName:

<Label Text="What's your favorite color?" />
<RadioButton Content="Red"
            GroupName="colors" />
<RadioButton Content="Green"
            GroupName="colors" />
<RadioButton Content="Blue"
            GroupName="colors" />
<RadioButton Content="Other"
            GroupName="colors" />

В данном примере каждый RadioButton является взаимоисключающим, поскольку имеет одно и то же значение GroupName.

Явная группировка с помощью вложенного свойства RadioButtonGroup.GroupName

Класс RadioButtonGroup определяет вложенное свойство GroupName типа string, которое может быть установлено на объект Layout. Это позволяет превратить любой макет в группу радиокнопок:

<StackLayout RadioButtonGroup.GroupName="colors">
   <Label Text="What's your favorite color?" />
   <RadioButton Content="Red" />
   <RadioButton Content="Green" />
   <RadioButton Content="Blue" />
   <RadioButton Content="Other" />
</StackLayout>

В этом примере для каждой RadioButton в StackLayout свойство GroupName будет иметь значение color, и они будут взаимоисключающими.

Примечание. Если объект Layout, устанавливающий вложенное свойство RadioButtonGroup.GroupName, содержит RadioButton, устанавливающий свое свойство GroupName, то значение свойства RadioButton.GroupName будет иметь приоритет.

Реакция на изменение состояния RadioButton

Переключатель имеет два состояния: установлен или не установлен. Когда он установлен, то свойство IsChecked равно true. Когда RadioButton не установлена, ее свойство IsChecked равно false. Переключатель можно очистить, нажав на другой в той же группе, но нельзя очистить, нажав на него еще раз. Однако выбор переключателя можно отменить программно, установив для ее свойства IsChecked значение false.

Реакция на срабатывание события

Когда свойство IsChecked изменяется в результате пользовательских или программных манипуляций, срабатывает событие CheckedChanged. Для этого события можно зарегистрировать обработчик, который будет реагировать на изменение:

<RadioButton Content="Red"
            GroupName="colors"
            CheckedChanged="OnColorsRadioButtonCheckedChanged" />
В code-behind содержится обработчик события CheckedChanged:
void OnColorsRadioButtonCheckedChanged(object sender, CheckedChangedEventArgs e)
{
   // Perform required operation
}

Аргумент sender – это RadioButton, отвечающий за данное событие. Его можно использовать для доступа к объекту RadioButton или для различения нескольких объектов RadioButton, имеющих один и тот же обработчик события CheckedChanged.

Реакция на изменение свойства

Класс RadioButtonGroup определяет вложенное свойство SelectedValue типа object, которое может быть установлено на объекте Layout. Это присоединенное свойство представляет собой значение отмеченной RadioButton в группе, определенной на макете.

При изменении свойства IsChecked в результате пользовательских или программных манипуляций изменяется и присоединенное свойство RadioButtonGroup.SelectedValue. Поэтому вложенное свойство RadioButtonGroup.SelectedValue может быть привязано к свойству, хранящему выбор пользователя:

<StackLayout RadioButtonGroup.GroupName="{Binding GroupName}"
            RadioButtonGroup.SelectedValue="{Binding Selection}">
   <Label Text="What's your favorite animal?" />
   <RadioButton Content="Cat"
                Value="Cat" />
   <RadioButton Content="Dog"
                Value="Dog" />
   <RadioButton Content="Elephant"
                Value="Elephant" />
   <RadioButton Content="Monkey"
                Value="Monkey"/>
   <Label x:Name="animalLabel">
       <Label.FormattedText>
           <FormattedString>
               <Span Text="You have chosen:" />
               <Span Text="{Binding Selection}" />
           </FormattedString>
       </Label.FormattedText>
   </Label>
</StackLayout>

В данном примере значение присоединенного свойства RadioButtonGroup.GroupName задается свойством GroupName контекста привязки. Аналогично, значение присоединенного свойства RadioButtonGroup.SelectedValue устанавливается свойством Selection контекста привязки. Кроме того, свойство Selection обновляется до значения свойства Value отмеченной кнопки RadioButton.

Визуальные состояния RadioButton

Объекты RadioButton имеют визуальные состояния Checked и Unchecked, которые можно использовать для инициирования визуальных изменений при установке или снятии флажка с RadioButton.

В следующем примере XAML показано, как определить визуальное состояние для состояний Checked и Unchecked:

<ContentPage ...>
   <ContentPage.Resources>
       <Style TargetType="RadioButton">
           <Setter Property="VisualStateManager.VisualStateGroups">
               <VisualStateGroupList>
                   <VisualStateGroup x:Name="CheckedStates">
                       <VisualState x:Name="Checked">
                           <VisualState.Setters>
                               <Setter Property="TextColor"
                                       Value="Green" />
                               <Setter Property="Opacity"
                                       Value="1" />
                           </VisualState.Setters>
                       </VisualState>
                       <VisualState x:Name="Unchecked">
                           <VisualState.Setters>
                               <Setter Property="TextColor"
                                       Value="Red" />
                               <Setter Property="Opacity"
                                       Value="0.5" />
                           </VisualState.Setters>
                       </VisualState>
                   </VisualStateGroup>
               </VisualStateGroupList>
           </Setter>
       </Style>
   </ContentPage.Resources>
   <StackLayout>
       <Label Text="What's your favorite mode of transport?" />
       <RadioButton Content="Car" />
       <RadioButton Content="Bike" />
       <RadioButton Content="Train" />
       <RadioButton Content="Walking" />
   </StackLayout>
</ContentPage>

В данном примере неявный стиль предназначен для объектов RadioButton. Визуальное состояние Checked определяет, что когда RadioButton находится в отмеченном состоянии, его свойство TextColor будет установлено в зеленый цвет со значением Opacity, равным 1. Визуальное состояние Unchecked определяет, что когда RadioButton находится в неконтролируемом состоянии, его свойство TextColor будет установлено в красный цвет со значением Opacity, равным 0,5. Таким образом, общий эффект заключается в том, что когда RadioButton не отмечен, он красный и частично прозрачный, а когда отмечен – зеленый без прозрачности:

Изменение внешнего вида RadioButton

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

В следующем XAML показан шаблон ControlTemplate, который можно использовать для переопределения визуальной структуры объектов RadioButton:

<ContentPage ...>
   <ContentPage.Resources>
       <ControlTemplate x:Key="RadioButtonTemplate">
           <Frame BorderColor="#F3F2F1"
                  BackgroundColor="#F3F2F1"
                  HasShadow="False"
                  HeightRequest="100"
                  WidthRequest="100"
                  HorizontalOptions="Start"
                  VerticalOptions="Start"
                  Padding="0">
               <VisualStateManager.VisualStateGroups>
                   <VisualStateGroupList>
                       <VisualStateGroup x:Name="CheckedStates">
                           <VisualState x:Name="Checked">
                               <VisualState.Setters>
                                   <Setter Property="BorderColor"
                                           Value="#FF3300" />
                                   <Setter TargetName="check"
                                           Property="Opacity"
                                           Value="1" />
                               </VisualState.Setters>
                           </VisualState>
                           <VisualState x:Name="Unchecked">
                               <VisualState.Setters>
                                   <Setter Property="BackgroundColor"
                                           Value="#F3F2F1" />
                                   <Setter Property="BorderColor"
                                           Value="#F3F2F1" />
                                   <Setter TargetName="check"
                                           Property="Opacity"
                                           Value="0" />
                               </VisualState.Setters>
                           </VisualState>
                       </VisualStateGroup>
                   </VisualStateGroupList>
               </VisualStateManager.VisualStateGroups>
               <Grid Margin="4"
                     WidthRequest="100">
                   <Grid WidthRequest="18"
                         HeightRequest="18"
                         HorizontalOptions="End"
                         VerticalOptions="Start">
                       <Ellipse Stroke="Blue"
                                Fill="White"
                                WidthRequest="16"
                                HeightRequest="16"
                                HorizontalOptions="Center"
                                VerticalOptions="Center" />
                       <Ellipse x:Name="check"
                                Fill="Blue"
                                WidthRequest="8"
                                HeightRequest="8"
                                HorizontalOptions="Center"
                                VerticalOptions="Center" />
                   </Grid>
                   <ContentPresenter />
               </Grid>
           </Frame>
       </ControlTemplate>
 
       <Style TargetType="RadioButton">
           <Setter Property="ControlTemplate"
                   Value="{StaticResource RadioButtonTemplate}" />
       </Style>
   </ContentPage.Resources>
   <!-- Page content -->
</ContentPage>

В данном примере корневым элементом шаблона ControlTemplate является объект Frame, определяющий визуальные состояния Checked и Unchecked. Объект Frame использует комбинацию объектов Grid, Ellipse и ContentPresenter для определения визуальной структуры RadioButton. Пример также включает неявный стиль, который присваивает шаблон RadioButtonTemplate свойству ControlTemplate всех объектов RadioButton на странице.

Примечание. Объект ContentPresenter отмечает место в визуальной структуре, где будет отображаться содержимое RadioButton.

В следующем XAML показаны объекты RadioButton, которые используют шаблон ControlTemplate с помощью неявного стиля:

<StackLayout>
   <Label Text="What's your favorite animal?" />
   <StackLayout RadioButtonGroup.GroupName="animals"
                Orientation="Horizontal">
       <RadioButton Value="Cat">
           <RadioButton.Content>
               <StackLayout>
                   <Image Source="cat.png"
                          HorizontalOptions="Center"
                          VerticalOptions="CenterAndExpand" />
                   <Label Text="Cat"
                          HorizontalOptions="Center"
                          VerticalOptions="End" />
               </StackLayout>
           </RadioButton.Content>
       </RadioButton>
       <RadioButton Value="Dog">
           <RadioButton.Content>
               <StackLayout>
                   <Image Source="dog.png"
                          HorizontalOptions="Center"
                          VerticalOptions="CenterAndExpand" />
                   <Label Text="Dog"
                          HorizontalOptions="Center"
                          VerticalOptions="End" />
               </StackLayout>
           </RadioButton.Content>
       </RadioButton>
       <RadioButton Value="Elephant">
           <RadioButton.Content>
               <StackLayout>
                   <Image Source="elephant.png"
                          HorizontalOptions="Center"
                          VerticalOptions="CenterAndExpand" />
                   <Label Text="Elephant"
                          HorizontalOptions="Center"
                          VerticalOptions="End" />
               </StackLayout>
           </RadioButton.Content>
       </RadioButton>
       <RadioButton Value="Monkey">
           <RadioButton.Content>
               <StackLayout>
                   <Image Source="monkey.png"
                          HorizontalOptions="Center"
                          VerticalOptions="CenterAndExpand" />
                   <Label Text="Monkey"
                          HorizontalOptions="Center"
                          VerticalOptions="End" />
               </StackLayout>
           </RadioButton.Content>
       </RadioButton>
   </StackLayout>
</StackLayout>

В этом примере визуальная структура, определенная для каждой кнопки RadioButton, заменяется визуальной структурой, определенной в шаблоне ControlTemplate, и, таким образом, во время выполнения программы объекты шаблона ControlTemplate становятся частью визуального дерева для каждой кнопки RadioButton. Кроме того, содержимое каждой кнопки RadioButton подставляется в ContentPresenter, определенный в шаблоне элемента управления. Это приводит к следующему виду RadioButton:

Материалы по теме