3 Mayıs 2016 Salı

You do not have sufficient privilege to access IIS web sites on your machine. (How dare you!)


Eğer Run as Administrator demezseniz Visual Studio şu şekıl çemkirebiliyor;

"The Web Application Project ..... is configured to use IIS.  Unable to access the IIS metabase. You do not have sufficient privilege to access IIS web sites on your machine."

Kes senini ben senin patronunum demek için, Run as administrator demeyi seçin. :P

Xamarin MessagingCenter'la ListView kullanarak picker sayfası oluşturma


Xamarin dünyasına girdiğimde Xamarin'e dair hiçbirşey bilmiyordum.. Azıcık C# bilgimle, deneme yanılma yöntemleriyle ve en çok da hocamın yardımlarıyla projeyi daha önce kullanmış olduğumuz javascript tabanlı platformdan hızlıca Xamarin'e geçirme çalışmalarına başladık. (çok şükür)

Pek çok yerde C#'ın event handler mantığını kullandık -ki ben bunu bile bu projede öğrendim.- . Daha sonra öğrendik ki meğer Xamarin'in MessagingCenter diye birşeyi varmış :) Bu MessagingCenter event handler ı sadeleştiren güzel bir yapı. Kısaca bir sayfadan başka bir sayfaya ya da sayfalara mesaj gönderiyoruz ve bu mesaja göre diğer sayfa(lar) aksiyon alıyor.

MessagingCenter örneklerini, uygulamalarını Xamarin'in sitesinde ve google amcada bulabiliriz. Örneğin;
https://developer.xamarin.com/guides/xamarin-forms/messaging-center/

Ben MessagingCenter'ı farklı bir şekilde nasıl kullandığımızı aktarmak istiyorumm. Projemizde kişi seçmemizi gerektiren, ya da listeden açıklamalı başka birşeyleri seçmemizi gerektiren pek çok bölüm var. Sürekli tekrarlı kod yazmaktansa bunu genel bir yapı haline getirip heryerde kullanalım diye düşündük. E peki nasıl? her kullandığımız yer için sayfanın aldığı parametreler de, listeden seçim yapıldığında tetiklecenecek metod da farklı. En pratik MessagingCenter kullanabiliriz diye düşündük :)

Öncelikle içinde ListView olan sade bir sayfa oluşturduk. Xaml'i;

  <ContentPage.Content>
    <ListView HasUnevenRows="true" x:Name="lvPicker" SeparatorColor="#e7e7e7" BackgroundColor="White" SeparatorVisibility="Default" VerticalOptions="FillAndExpand">
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Spacing="4" Padding="10">
              <Label FontSize="Large" Text="{Binding Title}" />
              <Label FontSize="Small" TextColor="Gray" IsVisible="{Binding HasDescription}" Text="{Binding Description}" />
            </StackLayout>
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>
  </ContentPage.Content>


Kodu;


public partial class PagePicker : ContentPage
{
    string _sender;
    List<PickerItem_items;
    public PagePicker(string sender, List<PickerItem> items)
    {
        InitializeComponent();
        _sender = sender;
        _items = items;
        lvPicker.ItemsSource = _items;
        lvPicker.ItemTapped += LvPicker_ItemTapped;
        //Buraya kapatma demek olan çarpılı bir image koyduk. Siz de koyun :)
        ToolbarItems.Add(new ToolbarItem("Close""closeModal.png"async () =>
        {
            await Navigation.PopModalAsync();
        }, ToolbarItemOrder.Primary));
    }
 
    async void LvPicker_ItemTapped(object sender, ItemTappedEventArgs e)
    {
        MessagingCenter.Send(_sender, "PickerItemSelected", (PickerItem)lvPicker.SelectedItem);
        await Navigation.PopModalAsync();
    }
}

Basitçe modelimiz;

public class PickerItem
 {
  public string Title { getset; }
  public string Description { getset; }
  public bool HasDescription => !string.IsNullOrEmpty(Description);
  public string Value { getset; }
 }


Burada "LvPicker_ItemTapped" metodunda MessagingCenter'la Mesajımızı gönderdik. Peki nereye gönderdik? O da parametrik :)

Burada Subscribe öncesinde Unsubscribe yapıyor olmamızın amacı karışıklığı önlemek. MessagingCenter'la ilgili ufak bir püf nokta daha; eğer tek yerden Send edip birkaç yerden karşılamak istiyorsanız "sender"'larınızın farklı olmasına dikkat edin, yoksa sadece birini çalıştırıp diğerlerini takmaz.

Mesajı karşıladığımız genel metodumuz;

public async static Task Picker(this ContentPage page, string title, List<PickerItem> items, Action<stringPickerItem> action)
{
 var type = page.GetType();
 if (type == null)
 return;

 var sender = type.Name;
 MessagingCenter.Unsubscribe<string>(sender, "PickerItemSelected");
 MessagingCenter.Subscribe(sender, "PickerItemSelected", action);
 
 var navPage = new NavigationPage(new PagePicker(sender, items));
 navPage.Title = title ?? page.T("global.choose");
 navPage.BarBackgroundColor = Color.FromHex(MBConsts.TitleBgColor);
 navPage.BarTextColor = Color.FromHex(MBConsts.TitleTextColor);
 
 await page.Navigation.PushModalAsync(navPage);
}


Genel ListView sayfamız hazır. Artık istediğimiz yerden bu sayfayı çağırıp içine istediğimiz datayı gönderip istediğimiz aksiyonu aldırabiliriz :)

Örneğin;

try
{
    if (_accounts != null)
    {
        var items = _accounts.Select(a => new PickerItem
        {
            Description = a.HesapKodu,
            Title = a.HesapAdi,
            Value = a.HesapKodu
        }).ToList();
 
        await this.Picker(null, items, (sender, item) =>
         {
             //Picker'ımızdan bir item seçildiğinde alınacak aksiyonlar;
             lblAccountType.Text = item.Title;
             _accountId = item.Value;
         });
    }
}
catch (Exception ex)
{
    Log(ex);
}


Hoşçakalın cinlerim. Ben proje ile debelenmeye devam edeyim :)