如何实现'Xamarin.Forms Two bindable properties inside a DataTemplateView'?
How to implement 'Xamarin.Forms Two bindable properties inside a DataTemplateView'?
我正在研究这种代码
我的图片资源class
[ContentProperty(nameof(Source))]
class ImageResourceExtension : IMarkupExtension
{
public string Source { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
var newImageSource = ImageSource.FromResource(Source, typeof(ImageResourceExtension).GetTypeInfo().Assembly);
return newImageSource;
}
}
我的列表模型class
class ListModel
{
public string IconSource { get; set; }
public string IconPath { get; set; }
}
我的 MyViewModel class
class MyViewModel : INotifyPropertyChanged
{
public List<Models.ListModel> MyListModel { get; }
public Command MyListCommand { get; }
public MyViewModel()
{
MyListModel = new List<Models.ListModel>()
{
new Models.ListModel(){ IconSource="https://example.com/image1",IconPath="MyImage1.jpg"},
new Models.ListModel(){ IconSource="https://example.com/image2",IconPath="MyImage2.jpg"}
};
MyListCommand = new Command(OnListClicked);
}
private async void OnListClicked(object value)
{
string valueString = value as string;
await Launcher.OpenAsync(valueString);
}
}
我的观点class
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:images="clr-namespace:MyProject.Images"
xmlns:models="clr-namespace:MyProject.Models"
xmlns:viewModels="clr-namespace:MyProject.ViewModels"
...
<ContentPage.BindingContext>
<viewModels:MyViewModel/>
</ContentPage.BindingContext>
<ContentPage.Content>
<StackLayout BindableLayout.ItemsSource="{Binding MyListModel}">
<BindableLayout.ItemTemplate>
<DataTemplate> <!-- line{setup path} -->
<Image Source="{images:ImageResource Source={Binding Source={RelativeSource AncestorType={x:Type viewModels:MyListModel}}, Path=ImageSource}}">
<Image.GestureRecognizers>
<TapGestureRecognizer
NumberOfTapsRequired="1"
Command="{Binding Source={RelativeSource AncestorType={x:Type viewModels:MyListModel}}, Path=MyListCommand}"
CommandParameter="{Binding ImagePath}"/>
</Image.GestureRecognizers>
</Image>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</ContentPage.Content>
我的问题是如何在此line: {setup path}
为我的图像源设置动态或可绑定属性?
如果您能解决这个问题,我将不胜感激。
谢谢。
已编辑: 我忘记添加我的图像 Embedded resource
在我的共享代码中。
您可以使用Value Converters来实现这个功能。
假设您的图像放置在您的 xamarin 表单项目的文件夹 Images
中(例如 MyFormDemo
)。
1.create EmbeddedToImageSourceConverter.cs
public class EmbeddedToImageSourceConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string ResourceId = value.ToString();
if (String.IsNullOrWhiteSpace(ResourceId))
return null;
return ImageSource.FromResource(ResourceId);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
2.InMyViewModel.cs
的构造函数,初始化IconPath
如下(添加MyFormDemo.Images.
):
public MyViewModel()
{
MyListModel = new List<ListModel>()
{
new ListModel(){ IconSource="https://example.com/image1",IconPath="MyFormDemo.Images.cherry.png"},
new ListModel(){ IconSource="https://example.com/image2",IconPath="MyFormDemo.Images.love.png"}
};
MyListCommand = new Command(OnListClicked);
}
3.Implement 接口 INotifyPropertyChanged
用于 class ListModel
:
public class ListModel: INotifyPropertyChanged
{
public string IconSource { get; set; }
//public string IconPath { get; set; }
string _iconPath;
public string IconPath
{
set { SetProperty(ref _iconPath, value); }
get { return _iconPath; }
}
bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Object.Equals(storage, value))
return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
4.in xaml 您的页面:
<ContentPage.Resources>
<MyFormDemo:EmbeddedToImageSourceConverter x:Key="converter">
</MyFormDemo:EmbeddedToImageSourceConverter>
</ContentPage.Resources>
<ContentPage.BindingContext>
<viewmodel:MyViewModel></viewmodel:MyViewModel>
</ContentPage.BindingContext>
<ContentPage.Content>
<StackLayout BindableLayout.ItemsSource="{Binding MyListModel}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<!-- line{setup path} -->
<Image Source="{Binding IconPath, Converter={StaticResource converter}}" WidthRequest="60" HeightRequest=" 60" BackgroundColor="Gray">
</Image>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</ContentPage.Content>
我正在研究这种代码
我的图片资源class
[ContentProperty(nameof(Source))]
class ImageResourceExtension : IMarkupExtension
{
public string Source { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
var newImageSource = ImageSource.FromResource(Source, typeof(ImageResourceExtension).GetTypeInfo().Assembly);
return newImageSource;
}
}
我的列表模型class
class ListModel
{
public string IconSource { get; set; }
public string IconPath { get; set; }
}
我的 MyViewModel class
class MyViewModel : INotifyPropertyChanged
{
public List<Models.ListModel> MyListModel { get; }
public Command MyListCommand { get; }
public MyViewModel()
{
MyListModel = new List<Models.ListModel>()
{
new Models.ListModel(){ IconSource="https://example.com/image1",IconPath="MyImage1.jpg"},
new Models.ListModel(){ IconSource="https://example.com/image2",IconPath="MyImage2.jpg"}
};
MyListCommand = new Command(OnListClicked);
}
private async void OnListClicked(object value)
{
string valueString = value as string;
await Launcher.OpenAsync(valueString);
}
}
我的观点class
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:images="clr-namespace:MyProject.Images"
xmlns:models="clr-namespace:MyProject.Models"
xmlns:viewModels="clr-namespace:MyProject.ViewModels"
...
<ContentPage.BindingContext>
<viewModels:MyViewModel/>
</ContentPage.BindingContext>
<ContentPage.Content>
<StackLayout BindableLayout.ItemsSource="{Binding MyListModel}">
<BindableLayout.ItemTemplate>
<DataTemplate> <!-- line{setup path} -->
<Image Source="{images:ImageResource Source={Binding Source={RelativeSource AncestorType={x:Type viewModels:MyListModel}}, Path=ImageSource}}">
<Image.GestureRecognizers>
<TapGestureRecognizer
NumberOfTapsRequired="1"
Command="{Binding Source={RelativeSource AncestorType={x:Type viewModels:MyListModel}}, Path=MyListCommand}"
CommandParameter="{Binding ImagePath}"/>
</Image.GestureRecognizers>
</Image>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</ContentPage.Content>
我的问题是如何在此line: {setup path}
为我的图像源设置动态或可绑定属性?
如果您能解决这个问题,我将不胜感激。 谢谢。
已编辑: 我忘记添加我的图像 Embedded resource
在我的共享代码中。
您可以使用Value Converters来实现这个功能。
假设您的图像放置在您的 xamarin 表单项目的文件夹 Images
中(例如 MyFormDemo
)。
1.create EmbeddedToImageSourceConverter.cs
public class EmbeddedToImageSourceConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string ResourceId = value.ToString();
if (String.IsNullOrWhiteSpace(ResourceId))
return null;
return ImageSource.FromResource(ResourceId);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
2.InMyViewModel.cs
的构造函数,初始化IconPath
如下(添加MyFormDemo.Images.
):
public MyViewModel()
{
MyListModel = new List<ListModel>()
{
new ListModel(){ IconSource="https://example.com/image1",IconPath="MyFormDemo.Images.cherry.png"},
new ListModel(){ IconSource="https://example.com/image2",IconPath="MyFormDemo.Images.love.png"}
};
MyListCommand = new Command(OnListClicked);
}
3.Implement 接口 INotifyPropertyChanged
用于 class ListModel
:
public class ListModel: INotifyPropertyChanged
{
public string IconSource { get; set; }
//public string IconPath { get; set; }
string _iconPath;
public string IconPath
{
set { SetProperty(ref _iconPath, value); }
get { return _iconPath; }
}
bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Object.Equals(storage, value))
return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
4.in xaml 您的页面:
<ContentPage.Resources>
<MyFormDemo:EmbeddedToImageSourceConverter x:Key="converter">
</MyFormDemo:EmbeddedToImageSourceConverter>
</ContentPage.Resources>
<ContentPage.BindingContext>
<viewmodel:MyViewModel></viewmodel:MyViewModel>
</ContentPage.BindingContext>
<ContentPage.Content>
<StackLayout BindableLayout.ItemsSource="{Binding MyListModel}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<!-- line{setup path} -->
<Image Source="{Binding IconPath, Converter={StaticResource converter}}" WidthRequest="60" HeightRequest=" 60" BackgroundColor="Gray">
</Image>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</ContentPage.Content>