我有一张带图片的自定义视图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
}
}
我已点击OriginalImage
按钮将下一张图片设置为Continue
属性但不会更改。我还想设置CropTopLeftX / Y / Width / Heigh
有人可以指导我吗?
答案 0 :(得分:0)
您的viewmodel需要实现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方法。
答案 1 :(得分:0)
它没有变化,因为你没有通知变化。您的ViewModel需要从 public ActionResult NoAccess()
{
Response.TrySkipIisCustomErrors = true;
Response.StatusCode = 403;
return View();
}
继承并在属性的setter中实现通知。
INotifyPropertyChanged