【发布时间】:2016-11-19 10:41:19
【问题描述】:
我正在为 my Github repository 开发 xamarin 解决方案。对于Pins project,我遇到了问题。事情是这样的,如果您创建一个图钉(又名CustomPin()),然后您想编辑该位置。然后地址名称将更改,如果您更改地址,位置将相同,位置将基于地址名称创建。所以从这里开始,很容易。
但是,当 Pin 地址/位置发生变化时,我希望自己的地图更新。但是因为 List 属性没有改变,所以它不会更新地图。
那么,获取指向父列表或地图的指针?
但是这个解决方案似乎不太适合我的使用,我认为也许存在另一个最佳解决方案,但我不知道该怎么做..
你可以编译项目,但是有三个更新。
自定义密码
public class CustomPin : BindableObject
{
public static readonly BindableProperty AddressProperty =
BindableProperty.Create(nameof(Address), typeof(string), typeof(CustomPin), "",
propertyChanged: OnAddressPropertyChanged);
public string Address
{
get { return (string)GetValue(AddressProperty); }
set { SetValue(AddressProperty, value); }
}
private static async void OnAddressPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
(bindable as CustomPin).SetValue(LocationProperty, await CustomMap.GetAddressPosition(newValue as string));
}
public static readonly BindableProperty LocationProperty =
BindableProperty.Create(nameof(Location), typeof(Position), typeof(CustomPin), new Position(),
propertyChanged: OnLocationPropertyChanged);
public Position Location
{
get { return (Position)GetValue(LocationProperty); }
set { SetValue(LocationProperty, value); }
}
private static async void OnLocationPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
(bindable as CustomPin).SetValue(AddressProperty, await CustomMap.GetAddressName((Position)newValue));
Debug.WriteLine("private static async void OnLocationPropertyChanged(BindableObject bindable, object oldValue, object newValue)");
}
public string Name { get; set; }
public string Details { get; set; }
public string ImagePath { get; set; }
public uint PinSize { get; set; }
public uint PinZoomVisibilityMinimumLimit { get; set; }
public uint PinZoomVisibilityMaximumLimit { get; set; }
public Point AnchorPoint { get; set; }
public Action<CustomPin> PinClickedCallback { get; set; }
public CustomPin(Position location)
{
Location = location;
Name = "";
Details = "";
ImagePath = "";
PinSize = 50;
PinZoomVisibilityMinimumLimit = uint.MinValue;
PinZoomVisibilityMaximumLimit = uint.MaxValue;
AnchorPoint = new Point(0.5, 1);
PinClickedCallback = null;
}
public CustomPin(string address)
{
Address = address;
Name = "";
Details = "";
ImagePath = "";
PinSize = 50;
PinZoomVisibilityMinimumLimit = uint.MinValue;
PinZoomVisibilityMaximumLimit = uint.MaxValue;
AnchorPoint = new Point(0.5, 1);
PinClickedCallback = null;
}
public CustomPin()
{
Address = "";
Location = new Position();
Name = "";
Details = "";
ImagePath = "";
PinSize = 50;
PinZoomVisibilityMinimumLimit = uint.MinValue;
PinZoomVisibilityMaximumLimit = uint.MaxValue;
AnchorPoint = new Point(0.5, 1);
PinClickedCallback = null;
}
}
自定义地图 | PS:只要加上这三个方法
#region
public async static Task<string> GetAddressName(Position position)
{
string url = "https://maps.googleapis.com/maps/api/geocode/json";
string additionnal_URL = "?latlng=" + position.Latitude + "," + position.Longitude
+ "&key=" + App.GOOGLE_MAP_API_KEY;
JObject obj = await CustomMap.GoogleAPIHttpRequest(url, additionnal_URL);
string address_name;
try
{
address_name = (obj["results"][0]["formatted_address"]).ToString();
}
catch (Exception)
{
return ("");
}
return (address_name);
}
public async static Task<Position> GetAddressPosition(string name)
{
string url = "https://maps.googleapis.com/maps/api/geocode/json";
string additionnal_URL = "?address=" + name
+ "&key=" + App.GOOGLE_MAP_API_KEY;
JObject obj = await CustomMap.GoogleAPIHttpRequest(url, additionnal_URL);
Position position;
try
{
position = new Position(Double.Parse((obj["results"][0]["geometry"]["location"]["lat"]).ToString()),
Double.Parse((obj["results"][0]["geometry"]["location"]["lng"]).ToString()));
}
catch (Exception)
{
position = new Position();
}
return (position);
}
private static async Task<JObject> GoogleAPIHttpRequest(string url, string additionnal_URL)
{
try
{
var client = new HttpClient();
client.BaseAddress = new Uri(url);
var content = new StringContent("{}", Encoding.UTF8, "application/json");
HttpResponseMessage response = null;
try
{
response = await client.PostAsync(additionnal_URL, content);
}
catch (Exception)
{
return (null);
}
string result = await response.Content.ReadAsStringAsync();
if (result != null)
{
try
{
return JObject.Parse(result);
}
catch (Exception)
{
return (null);
}
}
else
{
return (null);
}
}
catch (Exception)
{
return (null);
}
}
#endregion
MainPage.xaml.cs | PS:PCL 部分,只需更改 Constructor
public MainPage()
{
base.BindingContext = this;
CustomPins = new List<CustomPin>()
{
new CustomPin("Long Beach") { Name = "Le Mans", Details = "Famous city for race driver !", ImagePath = "CustomIconImage.png", PinZoomVisibilityMinimumLimit = 0, PinZoomVisibilityMaximumLimit = 150, PinSize = 75},
new CustomPin() { Name = "Ruaudin", Details = "Where I'm coming from.", ImagePath = "CustomIconImage.png", PinZoomVisibilityMinimumLimit = 75, PinSize = 65 },
new CustomPin() { Name = "Chelles", Details = "Someone there.", ImagePath = "CustomIconImage.png", PinZoomVisibilityMinimumLimit = 50, PinSize = 70 },
new CustomPin() { Name = "Lille", Details = "Le nord..", ImagePath = "CustomIconImage.png", PinZoomVisibilityMinimumLimit = 44, PinSize = 40 },
new CustomPin() { Name = "Limoges", Details = "I have been there ! :o", ImagePath = "CustomIconImage.png", PinZoomVisibilityMinimumLimit = 65, PinSize = 20 },
new CustomPin() { Name = "Douarnenez", Details = "A trip..", ImagePath = "CustomIconImage.png", PinZoomVisibilityMinimumLimit = 110, PinSize = 50 }
};
Debug.WriteLine("Initialization done.");
PinActionClicked = PinClickedCallback;
PinsSize = Convert.ToUInt32(100);
MinValue = 50;
MaxValue = 100;
InitializeComponent();
Debug.WriteLine("Components done.");
}
也许这很简单,或者我所说的方式是唯一的,但是如果图钉被编辑了,我不知道如何更新地图上的图钉,因为最终,它仍然是同一个对象,所以列表没有'不要改变......
感谢您的帮助!
编辑 1
好吧,我做了一些更改,但是仍然无法正常工作。我的意思是我的代码可以按我的意愿工作,但是调用 PropertyChanged 并没有改变任何内容...
我改变了一些东西,比如 List<CustomPin> 现在是 ObservableCollection<CustomPin>.. 我还把 xaml 部分改成了:
<control:CustomMap x:Name="MapTest" CustomPins="{Binding CustomPins}" CameraFocusParameter="OnPins"
PinSize="{Binding PinsSize, Converter={StaticResource Uint}}"
PinClickedCallback="{Binding PinActionClicked}"
VerticalOptions="Fill" HorizontalOptions="Fill"/>
而我的CustomPin 现在是这样的:
public class CustomPin : BindableObject, INotifyPropertyChanged
{
/// <summary>
/// Handler for event of updating or changing the
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
public static readonly BindableProperty AddressProperty =
BindableProperty.Create(nameof(Address), typeof(string), typeof(CustomPin), "",
propertyChanged: OnAddressPropertyChanged);
public string Address
{
get { return (string)GetValue(AddressProperty); }
set { SetValue(AddressProperty, value); }
}
private static void OnAddressPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
(bindable as CustomPin).SetAddress(newValue as string);
Debug.WriteLine("Address property changed");
}
private async void SetAddress(string address)
{
if (setter == SetFrom.None)
{
setter = SetFrom.Address;
SetLocation(await CustomMap.GetAddressPosition(address));
setter = SetFrom.None;
NotifyChanges();
}
else if (setter == SetFrom.Location)
{
setter = SetFrom.Done;
SetValue(AddressProperty, address);
}
}
private enum SetFrom
{
Address,
Done,
Location,
None,
}
private SetFrom setter;
private async void SetLocation(Position location)
{
if (setter == SetFrom.None)
{
setter = SetFrom.Location;
SetAddress(await CustomMap.GetAddressName(location));
setter = SetFrom.None;
NotifyChanges();
}
else if (setter == SetFrom.Address)
{
setter = SetFrom.Done;
SetValue(LocationProperty, location);
}
}
public static readonly BindableProperty LocationProperty =
BindableProperty.Create(nameof(Location), typeof(Position), typeof(CustomPin), new Position(),
propertyChanged: OnLocationPropertyChanged);
public Position Location
{
get { return (Position)GetValue(LocationProperty); }
set { SetValue(LocationProperty, value); }
}
private static async void OnLocationPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
(bindable as CustomPin).SetLocation((Position)newValue);
Debug.WriteLine("Location property changed");
}
private void NotifyChanges()
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Address)));
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Location)));
}
public string Name { get; set; }
public string Details { get; set; }
public string ImagePath { get; set; }
public uint PinSize { get; set; }
public uint PinZoomVisibilityMinimumLimit { get; set; }
public uint PinZoomVisibilityMaximumLimit { get; set; }
public Point AnchorPoint { get; set; }
public Action<CustomPin> PinClickedCallback { get; set; }
public CustomPin(Position location)
{
setter = SetFrom.None;
Location = location;
Name = "";
Details = "";
ImagePath = "";
PinSize = 50;
PinZoomVisibilityMinimumLimit = uint.MinValue;
PinZoomVisibilityMaximumLimit = uint.MaxValue;
AnchorPoint = new Point(0.5, 1);
PinClickedCallback = null;
}
public CustomPin(string address)
{
setter = SetFrom.None;
Address = address;
Name = "";
Details = "";
ImagePath = "";
PinSize = 50;
PinZoomVisibilityMinimumLimit = uint.MinValue;
PinZoomVisibilityMaximumLimit = uint.MaxValue;
AnchorPoint = new Point(0.5, 1);
PinClickedCallback = null;
}
public CustomPin()
{
setter = SetFrom.None;
Address = "";
Location = new Position();
Name = "";
Details = "";
ImagePath = "";
PinSize = 50;
PinZoomVisibilityMinimumLimit = uint.MinValue;
PinZoomVisibilityMaximumLimit = uint.MaxValue;
AnchorPoint = new Point(0.5, 1);
PinClickedCallback = null;
}
}
最后,PropertyChanged 的调用没有任何作用.. 有什么想法吗?
谢谢!
PS:不要忘记我的 github 存储库中提供了该解决方案
【问题讨论】:
-
您的 Pin 需要实现 INotifyPropertyChanged
-
好的,但是属性改变的参数是什么?
-
被更改的属性的名称
-
您好,我编辑了问题,您能再看一下吗?谢谢
标签: c# list xamarin.forms