#c# #xamarin.forms
#c# #xamarin.forms
Вопрос:
Я создаю пользовательский элемент управления с помощью CollectionView. Проблема в том, что я хочу предоставить ему ItemsSource с главной страницы, а не из элемента управления, и что ItemsSource связывает его с моей ViewModel, где находится моя ObservableCollection. Это мой код:
FloatingButton.xaml:
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CustomControlWithList.FloatingButton"
x:Name="FloatingButtonView">
<StackLayout>
<AbsoluteLayout>
<CollectionView
x:Name="listView"
Margin="0,0,36,0"
AbsoluteLayout.LayoutBounds="1,0,AutoSize,AutoSize"
AbsoluteLayout.LayoutFlags="PositionProportional"
BackgroundColor="Transparent"
ItemsSource="{Binding ItemSource}"
IsVisible="{Binding IsVisible}"
Rotation="180"
WidthRequest="60">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid
Padding="5"
HeightRequest="50"
WidthRequest="50">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!--This ImageButton contais the data of the list-->
<ImageButton
Padding="10"
BackgroundColor="{Binding ColorButton}"
Command="{Binding Source={x:Reference page}, Path=BindingContext.LaunchWeb}"
CommandParameter="{Binding Website}"
CornerRadius="70"
Rotation="180"
Source="{Binding Image}"
/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</AbsoluteLayout>
<ImageButton
Margin="15"
Padding="10"
WidthRequest="70"
HeightRequest="70"
BackgroundColor="{Binding PrimaryButtonColor}"
Command="{Binding OpenFloating}"
CornerRadius="70"
HorizontalOptions="End"
Source="{Binding PrimaryImageSource}"
VerticalOptions="EndAndExpand" />
</StackLayout>
</ContentView>
FloatingButton.xaml.cs:
public partial class FloatingButton : ContentView
{
//===============Item Source=====================
public static readonly BindableProperty ItemSourceProperty =
BindableProperty.Create("ItemSource", typeof(CollectionView),typeof(FloatingButton));
public CollectionView ItemSource
{
get { return (CollectionView)GetValue(ItemSourceProperty); }
set { SetValue(ItemSourceProperty, value); }
}
//=================================================Flo
//===============Primary Button Image=====================
public static readonly BindableProperty PrimaryImageSourceProperty =
BindableProperty.Create("PrimaryImageSource", typeof(ImageSource), typeof(FloatingButton));
public ImageSource PrimaryImageSource
{
get { return (ImageSource)GetValue(PrimaryImageSourceProperty); }
set { SetValue(PrimaryImageSourceProperty, value); }
}
//=============================================================
//===============Primary Button Color=====================
public static readonly BindableProperty PrimaryButtonColorProperty =
BindableProperty.Create("PrimaryButtonColor", typeof(Color), typeof(FloatingButton));
public Color PrimaryButtonColor
{
get { return (Color)GetValue(PrimaryButtonColorProperty); }
set { SetValue(PrimaryButtonColorProperty, value); }
}
//=============================================================
public FloatingButton()
{
InitializeComponent();
BindingContext = this;
}
}
MainPage.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CustomControlWithList.MainPage"
x:Name="page"
xmlns:local="clr-namespace:CustomControlWithList">
<local:FloatingButton
ItemSource="ItemList"
PrimaryImageSource="dots.png"
PrimaryButtonColor="Green"
/>
</ContentPage>
MainPage.xaml.cs:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new ViewModel();
}
}
ViewModel.cs:
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public ObservableCollection<Items> ItemList { get; set; }
private bool isVisible;
public bool IsVisible
{
get => isVisible;
set
{
isVisible = value;
OnPropertyChanged();
}
}
public ViewModel()
{
ItemList = new ObservableCollection<Items>();
ItemList.Add(new Items { Website = "https://facebook.com", Image = "facebook.png", ColorButton = "#B52D50" });
ItemList.Add(new Items { Website = "https://twitter.com", Image = "twitter.png", ColorButton = "#B52D50" });
ItemList.Add(new Items { Website = "https://www.instagram.com", Image = "insta.png", ColorButton = "#B52D50" });
}
}
Items.cs:
public class Items : INotifyPropertyChanged
{
string url, image, color;
public string Website
{
get { return url; }
set
{
url = value;
OnPropertyChanged("url");
}
}
public string Image
{
get
{
return image;
}
set
{
image = value;
OnPropertyChanged("image");
}
}
public string ColorButton
{
get
{
return color;
}
set
{
color = value;
OnPropertyChanged("color");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Ответ №1:
Вы могли бы установить ItemSource как связываемое свойство вместо всего CollectionView .
Кстати, поскольку вы использовали пользовательский вид, вам нужно напрямую задать путь привязки в xaml . Строка BindingContext = this;
разорвет привязку между CustomView и ContentPage .
Таким образом, вы можете изменить код следующим образом
в FloatingButton.xaml
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CustomControlWithList.FloatingButton"
x:Name="FloatingButtonView">
<StackLayout>
<AbsoluteLayout>
<CollectionView
x:Name="listView"
Margin="0,0,36,0"
AbsoluteLayout.LayoutBounds="1,0,AutoSize,AutoSize"
AbsoluteLayout.LayoutFlags="PositionProportional"
BackgroundColor="Transparent"
ItemsSource="{Binding Source={x:Reference FloatingButtonView}, Path=ItemSource}"
IsVisible="{{Binding Source={x:Reference FloatingButtonView}, Path=CollectionViewVisible}"
Rotation="180"
WidthRequest="60">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid
Padding="5"
HeightRequest="50"
WidthRequest="50">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!--This ImageButton contais the data of the list-->
<ImageButton
Padding="10"
BackgroundColor="{Binding ColorButton}"
Command="{{Binding Source={x:Reference FloatingButtonView}, Path=LaunchWeb}"
CommandParameter="{{Binding Source={x:Reference FloatingButtonView}, Path=Website}"
CornerRadius="70"
Rotation="180"
Source="{Binding Image}"
/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</AbsoluteLayout>
<ImageButton
Margin="15"
Padding="10"
WidthRequest="70"
HeightRequest="70"
BackgroundColor="{{Binding Source={x:Reference FloatingButtonView}, Path=PrimaryButtonColor}"
Command="{Binding Source={x:Reference FloatingButtonView}, Path=OpenFloating}"
CornerRadius="70"
HorizontalOptions="End"
Source="{{Binding Source={x:Reference FloatingButtonView}, Path=PrimaryImageSource}"
VerticalOptions="EndAndExpand" />
</StackLayout>
</ContentView>
public FloatingButton()
{
InitializeComponent();
// BindingContext = this;
}
//...
//===============Item Source=====================
public static readonly BindableProperty ItemSourceProperty =
BindableProperty.Create("ItemSource", typeof(ObservableCollection<Items>), typeof(FloatingButton));
public ObservableCollection<Items> ItemSource
{
get { return (ObservableCollection<>)GetValue(ItemSourceProperty); }
set { SetValue(ItemSourceProperty, value); }
}
public static readonly BindableProperty CollectionViewVisibleProperty =
BindableProperty.Create("PrimaryImageSource", typeof(bool), typeof(FloatingButton),false);
public bool CollectionViewVisible
{
get { return (bool)GetValue(CollectionViewVisibleProperty); }
set { SetValue(CollectionViewVisibleProperty, value); }
}
public static readonly BindableProperty LaunchWebProperty =
BindableProperty.Create(nameof(LaunchWeb), typeof(ICommand), typeof(FloatingButton));
public ICommand LaunchWeb
{
get => (ICommand)GetValue(LaunchWebProperty );
set => SetValue(LaunchWebProperty , value);
}
public static BindableProperty WebsiteProperty =
BindableProperty.Create(nameof(Website), typeof(object), typeof(FloatingButton));
public object Website
{
get => (object)GetValue(WebsiteProperty );
set => SetValue(WebsiteProperty , value);
}
//other bindable property like this
в ContentPage
Теперь вы можете установить привязку следующим образом
<local:FloatingButton
ItemSource="{Binging ItemList}"
CollectionViewVisible = "{Binding IsVisible}"
PrimaryImageSource="dots.png"
PrimaryButtonColor="Green"
/>