[英]How to set two way binding for Image control in Xamarin.Forms?
我有一个带有图像的自定义视图MyPhotoView
。 我已加载图片。 现在,我想在继续按钮单击时更改图像。 我尝试使用TwoWay Binding和Binding属性的设置值,但是单击“ Continue
按钮时图像不会更改。
上一页按钮单击//从上一页的ViewModel调用(从图库中获取图像)
List<Image> currentOriginalImages = new List<Image>();
foreach (var item in _pictureSources)
{
currentOriginalImages.Add(new Image() { Source = item });
}
var viewModel = new CropPhotoViewModel(currentOriginalImages);
XAML中使用的自定义控件MyPhotoView
public class MyPhotoView : View
{
public static readonly BindableProperty CropTopLeftXProperty =
BindableProperty.Create(nameof(CropTopLeftX), typeof (float), typeof (MyPhotoView), 0f, BindingMode.TwoWay);
public static readonly BindableProperty CropTopLeftYProperty =
BindableProperty.Create(nameof(CropTopLeftY), typeof (float), typeof (MyPhotoView), 0f, BindingMode.TwoWay);
public static readonly BindableProperty CropWidthProperty =
BindableProperty.Create(nameof(CropWidth), typeof (float), typeof (MyPhotoView), 0f, BindingMode.TwoWay);
public static readonly BindableProperty CropHeightProperty =
BindableProperty.Create(nameof(CropHeight), typeof (float), typeof (MyPhotoView), 0f, BindingMode.TwoWay);
public static readonly BindableProperty OriginalImageProperty =
BindableProperty.Create(nameof(OriginalImage), typeof (Image), typeof (MyPhotoView),null,BindingMode.TwoWay);
public float CropTopLeftX
{
get { return (float) GetValue(CropTopLeftXProperty); }
set { SetValue(CropTopLeftXProperty, value); }
}
public float CropTopLeftY
{
get { return (float) GetValue(CropTopLeftYProperty); }
set { SetValue(CropTopLeftYProperty, value); }
}
public float CropWidth
{
get { return (float) GetValue(CropWidthProperty); }
set { SetValue(CropWidthProperty, value); }
}
public float CropHeight
{
get { return (float) GetValue(CropHeightProperty); }
set { SetValue(CropHeightProperty, value); }
}
public Image OriginalImage
{
get { return (Image) GetValue(OriginalImageProperty); }
set { SetValue(OriginalImageProperty, value); }
}
}
XAML:
<?xml version="1.0" encoding="UTF-8"?>
<local:ContentPageWithCustomBackButton
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyProject;assembly=MyProject"
x:Class="MyProject.CropPhotoPage"
Title="Upload Photo">
<ContentPage.ToolbarItems>
<ToolbarItem Icon="icon-nav-back" Order="Primary" Priority="0" Command="{Binding GoBackCommand}" />
</ContentPage.ToolbarItems>
<ContentPage.Content>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<local:MyPhotoView Grid.Row="0" Grid.ColumnSpan="3"
x:Name="MyPhotoView"
OriginalImage="{Binding OriginalImage}"
CropTopLeftX="{Binding CropTopLeftX}"
CropTopLeftY="{Binding CropTopLeftY}"
CropWidth="{Binding CropWidth}"
CropHeight="{Binding CropHeight}" />
<Button Grid.Row="1" Grid.Column="0" Margin="20,0,0,19"
Text="Cancel" Clicked="CancelClicked" />
<Button Grid.Row="1" Grid.Column="2" Margin="0,0,20,19" Clicked="ContinueClicked"
Text="Continue" Command="{Binding ContinueCommand}" />
</Grid>
</ContentPage.Content>
</local:ContentPageWithCustomBackButton>
CS页面
public partial class CropPhotoPage : ContentPageWithCustomBackButton
{
public CropPhotoPage()
{
InitializeComponent();
BindingContext = App.Locator.CropPhoto;
}
public CropPhotoPage(CropPhotoViewModel bindingContext)
{
InitializeComponent();
BindingContext = bindingContext;
}
private void CancelClicked(object sender, EventArgs e)
{
MyPhotoView.ResetCrop();
}
private void ContinueClicked(object sender, EventArgs e)
{
MyPhotoView.ApplyCrop();
}
}
视图模型
public CropPhotoViewModel(List<Image> images)
{
ContinueCommand = new RelayCommand(async () => await ContinueCommandExecute());
_images = images;
OriginalImage = images[0];
}
public Image OriginalImage { get; set; }
public List<Image> _images { get; set; }
public float CropTopLeftX { get; set; }
public float CropTopLeftY { get; set; }
public float CropWidth { get; set; }
public float CropHeight { get; set; }
public int CurrentImageCounter { get; set; }
private async Task ContinueCommandExecute()
{
//crop the image
if(CurrentImageCounter == _images.Count)
return;
else
{
var croppedImage = _cropImageService.CropImageWithRect(_images[CurrentImageCounter],
new Rectangle(CropTopLeftX, CropTopLeftY, CropWidth, CropHeight));
CurrentImageCounter++;
//I want to change image here but it doesn't change even it is 2 way binding
OriginalImage = _images[CurrentImageCounter];
//I also want to set all 4 parameter of CropTopLeftX/Y/Width/Heigh here
}
}
我已经在单击“ Continue
按钮上将下一张图像设置为OriginalImage
属性,但是它没有更改。 我也想设置CropTopLeftX / Y / Width / Heigh的所有4个参数
有人可以指导我吗?
您的视图模型需要实现INotifyPropertyChanged接口:
YourViewModel : BaseClass, INotifyPropertyChanged
(...)
public event PropertyChangedEventHandler PropertyChanged = delegate { };
public void OnPropertyChanged([CallerMemberName]string propertyName="")
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
那么您需要将更改的事实通知所有绑定到您的属性的对象:
Image _originalImage;
public Image OriginalImage
{
get => _originalImage;
set
{
_originalImage = value;
OnPropertyChanged();
}
}
您需要在绑定到的每个属性设置器中调用OnPropertyChanged方法。
它不会更改,因为您没有通知更改。 您是ViewModel需要继承自INotifyPropertyChanged
并在属性的设置器中实现通知。
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private Image originalImage;
public Image OriginalImage
{
get => originalImage;
set
{
originalImage = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(OriginalImage)); //Notify the property is changing.
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.