NuGet Paket | Link | Repo Bilgi |
---|---|---|
FmgLib.MauiMarkup |
||
FmgLib.MauiMarkup.Template |
- |
<br>
FmgLib.MauiMarkup, .NET MAUI için özel olarak tasarlanmış bir kütüphanedir. Bu kütüphane, XAML dilini kullanma zorunluluğu olmaksızın doğrudan C# kodu ile kodlama yapmanızı sağlar. Geliştiricilere, C# kodu kullanarak kullanıcı arayüzleri oluşturma konusunda basit ve esnek bir yaklaşım sunar. FmgLib.MauiMarkup ile artık uygulama arayüzlerini kod odaklı bir şekilde geliştirebilir, XAML dosyalarıyla ilgili karmaşıklıklarla uğraşmanın önüne geçebilirsiniz. Bu kütüphane, geliştirme sürecinizi hızlandırırken daha okunabilir ve yönetilebilir kod yazmanızı sağlar.
FmgLib.MauiMarkup, XAML tarafında bir Görünüm için sağlanan tüm özellikler için uzantı metotları sunar.
FmgLib, FmgLib.MauiMarkup ile yeni bir proje başlatmak için bir proje şablonu sağlar.
NuGet'ten en son şablonları yükleyin:
dotnet new install FmgLib.MauiMarkup.Template
Yeni proje oluştur:
dotnet new fmglib-mauimarkup-app -o my-new-project
<br>
MAUI uygulamanıza FmgLib.MauiMarkup NuGet paketini yüklemek için:
dotnet add package FmgLib.MauiMarkup
Eğer Image sınıfı için XAML kodu yazacak olsaydık, aşağıdaki gibi görünürdü:
<Image
Source="dotnet_bot.png"
HeightRequest="100"
WidthRequest="150"
Grid.Row="0"
Grid.Column="1"
Grid.RowSpan="2"
Opacity=".8" />
FmgLib.MauiMarkup yardımı ile C# karşılığı şu şekilde olacaktır:
new Image()
.Source("dotnet_bot.png")
.Row(0)
.Column(1)
.RowSpan(2)
.SizeRequest(150,100)
.Opacity(.8)
Benzer şekilde, diğer Görünümler için de bunu görebiliriz. Örnek olarak birkaç kod yazalım:
new Label()
.Text("fmglib.mauimarkup")
.FontSize(12)
.Row(1)
.TextColor(Colors.Green)
.FontAttributes(FontAttributes.Bold)
.Margin(new Thickness(5,3,0,5))
this
.BackgroundImageSource("background.jpg")
.Content(
new StackLayout()
.Center()
.Children(
new ActivityIndicator()
.IsRunning(true)
.HeightRequest(70)
.WidthRequest(70)
.Center()
.InvokeOnElement(ai => ai.Loaded += CheckLogin(sender, e))
)
);
FmgLib.MauiMarkup
içinde nesne atamanın iki ana yolu vardır:
Assign
metodunu kullanarak,İlk örnek, Assign
metodunu kullanarak bir etiket nesnesini label adında bir değişkene atamaktadır. Bu, aşağıdaki kod ile yapılır:
new Label().Assign(out var label);
new Entry().Assign(out var entry);
Veya
Button btnOk;
new Button()
.Assign(out btnOk);
Bağlı özellikler, bir tür üzerinde tanımlanan ancak diğer türlerin örnekleriyle kullanılması amaçlanan özelliklerdir. FmgLib.MauiMarkup
içinde, bağlı özellikler bağlı özellik akıcı metodlarıyla eşleştirilir, böylece değerlerini daha okunabilir ve akıcı bir şekilde ayarlamanıza olanak tanır.
Örneğin, bir Border nesnesi üzerinde AbsoluteLayout.LayoutBounds
bağlı özelliğini ayarlamak istiyorsanız, bir Border örneği oluşturur ve değerini ayarlamak için AbsoluteLayoutBounds
akıcı metodunu kullanırsınız, şu şekilde:
new Border().AbsoluteLayoutBounds(new Rect(100, 100, 200, 200));
Bu, belirtilen dikdörtgen değerine Border
nesnesi üzerinde AbsoluteLayout.LayoutBounds
bağlı özelliğini ayarlar.
Maui bağlı özelliği | FmgLib.MauiMarkup metodu |
---|---|
FlyoutBase.ContextFlyout |
ContextFlyout() |
Grid.Column |
Column() |
Grid.Row |
Row() |
Grid.ColumnSpan |
ColumnSpan() |
Grid.RowSpan |
RowSpan() |
Grid.ColumnSpan +Grid.RowSpan |
Span(column, row) |
VisualStateManager.VisualStateGroups |
VisualStateGroups() |
RadioButtonGroup.GroupName |
RadioButtonGroupGroupName() |
RadioButtonGroup.SelectedValue |
RadioButtonGroupSelectedValue() |
AbsoluteLayout.LayoutFlags |
AbsoluteLayoutFlags() |
AbsoluteLayout.LayoutBounds |
AbsoluteLayoutBounds() |
BindableLayout.EmptyView |
BindableLayoutEmptyView() |
BindableLayout.EmptyViewTemplate |
BindableLayoutEmptyViewTemplate() |
BindableLayout.ItemsSource |
BindableLayoutItemsSource() |
BindableLayout.ItemTemplate |
BindableLayoutItemTemplate() |
BindableLayout.TemplateSelector |
BindableItemTemplateSelector() |
Shell.PresentationMode |
ShellPresentationMode() |
Shell.BackgroundColor |
ShellBackgroundColor() |
Shell.ForegroundColor |
ShellForegroundColor() |
Shell.TitleColor |
ShellTitleColor() |
Shell.DisabledColor |
ShellDisabledColor() |
Shell.UnselectedColor |
ShellUnselectedColor() |
Shell.NavBarHasShadow |
ShellNavBarHasShadow() |
Shell.NavBarIsVisible |
ShellNavBarIsVisible() |
Shell.TitleView |
ShellTitleView() |
Shell.TabBarBackgroundColor |
ShellTabBarBackgroundColor() |
Shell.TabBarForegroundColor |
ShellTabBarForegroundColor() |
Shell.TabBarTitleColor |
ShellTabBarTitleColor() |
Shell.TabBarDisabledColor |
ShellTabBarDisabledColor() |
Shell.TabBarUnselectedColor |
ShellTabBarUnselectedColor() |
Shell.TabBarIsVisible |
ShellTabBarIsVisible() |
Shell.FlyoutBackdrop |
ShellFlyoutBackdrop() |
Shell.FlyoutBehavior |
ShellFlyoutBehavior() |
Shell.FlyoutHeight |
ShellFlyoutHeight() |
Shell.FlyoutWidth |
ShellFlyoutWidth() |
Shell.FlyoutItemIsVisible |
ShellFlyoutItemIsVisible() |
Shell.BackButtonBehavior |
ShellBackButtonBehavior() |
Shell.ItemTemplate |
ShellItemTemplate() |
Shell.MenuItemTemplate |
ShellMenuItemTemplate() |
Shell.SearchHandler |
ShellSearchHandler() |
NavigationPage.HasNavigationBar |
NavigationPageHasNavigationBar() |
NavigationPage.BackButtonTitle |
NavigationPageBackButtonTitle() |
NavigationPage.HasBackButton |
NavigationPageHasBackButton() |
NavigationPage.IconColor |
NavigationPageIconColor() |
NavigationPage.TitleIconImageSource |
NavigationPageTitleIconImageSource() |
NavigationPage.TitleView |
NavigationPageTitleView() |
SemanticProperties.Hint |
SemanticHint() |
SemanticProperties.Description |
SemanticDescription() |
SemanticProperties.HeadingLevel |
SemanticHeadingLevel() |
AutomationProperties.ExcludedWithChildren |
AutomationExcludedWithChildren() |
AutomationProperties.IsInAccessibleTree |
AutomationIsInAccessibleTree() |
AutomationProperties.Name |
AutomationName() |
AutomationProperties.HelpText |
AutomationHelpText() |
AutomationProperties.LabeledBy |
AutomationLabeledBy() |
ToolTipProperties.Text |
ToolTipPropertiesText() |
FmgLib.MauiMarkup
içinde, kullanıcı arayüzü kontrollerine davranışlar ekleyerek işlevsellik kazandırabilirsiniz. Davranışlar, kontrolleri alt sınıfa ayırmadan onlara işlevsellik eklemenizi sağlar.
Bir kontrolün üzerine bir davranış eklemek için Behaviors
metodunu kullanabilir ve davranış sınıfının bir örneğini geçirebilirsiniz. Örneğin:
new Entry().Text("Click Item")
.Behaviors(new YourCustomBehaviors());
Bu kod, FmgLib.MauiMarkup
içinde BindingConverters'ları nasıl kullanılacağına dair bir örnektir.
Bir CollectionView
tanımlanmış ve MyNumbers
listesindeki her bir öğe için, öğenin değerine eşit metinle bir etiket oluşturulmuştur. Etiketin BackgroundColor
özelliği, öğeye bağlı olarak Convert
metodunu kullanarak bağlanmıştır, bu metod bir fonksiyon alır ve öğenin değerini (bir tamsayı) bir renge dönüştürür. Bu durumda, fonksiyon numaranın çift mi yoksa tek mi olduğunu kontrol eder ve sonuca göre ya Colors.Green
veya Colors.Yellow
döndürür.
public class CustomPage : ContentPage
{
public List<int> MyNumbers = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
public CustomPage()
{
this
.Content(
new VerticalStackLayout()
Children(
new CollectionView()
.ItemsSource(MyNumbers)
.ItemTemplate(() =>
new Label()
.FontSize(30)
.Text(e => e.Path("."))
.TextColor(Colors.Gray)
.BackgroundColor(e => e
.Path(".")
.Convert((int n) => n % 2 == 0 ? Colors.Green : Colors.Yellow)
)
)
)
);
}
}
Maui'de, kullanıcı arayüzü kontrollerine olayları işleyerek işlevsellik ekleyebilirsiniz. FmgLib.MauiMarkup
sınıfındaki her EventHandler
için, bir kontrolde olay işleyicisini eklemeyi kolaylaştıran akıcı bir yardımcı metod üretilir.
Örneğin, Button
sınıfındaki Clicked
olay işleyicisi için iki akıcı metod üretilir:
OnClicked(Button sender)
OnClicked(object sender, EventArgs e)
İşte Button
kontrolünde Clicked
olayını işlemek için akıcı yardımcı metod OnClicked
kullanma örneği:
using FmgLib.MauiMarkup;
public class ExamPage : ContentPage
{
int count = 0;
public ExamPage()
{
this
.Content(
new VerticalStackLayout()
.Children(
...
new Button()
.Text("Click me")
.OnClicked(OnCounterClicked),
...
)
);
}
private void OnCounterClicked(Button sender)
{
count++;
sender.Text = $"Clicked {count} ";
sender.Text += count == 1 ? "time" : "times";
}
}
Veya, olayı işlemek için bir satır içi fonksiyon kullanabilirsiniz:
new Button()
.Text("Click me")
.OnClicked(button =>
{
count++;
button.Text = $"Clicked {count} ";
button.Text += count == 1 ? "time" : "times";
})
Bu, olay işleyicilerini kontrollere açık ve okunaklı bir şekilde eklemeyi kolaylaştırır.
Aşağıdaki hareket tanıyıcıları mevcuttur:
TapGestureRecognizer
PanGestureRecognizer
PointerGestureRecognizer
TapGestureRecognizer
sınıfı, bir görünümde dokunma hareketlerini algılamak için kullanılır. NumberOfTapsRequired
özelliği kullanılarak gerekli dokunma sayısı belirtilebilir.
İşte bir resimde çift dokunma hareketini algılamak için TapGestureRecognizer kullanımına bir örnek:
new StackLayout()
.Children(
new Label()
.Text("Tap 2 times on the image")
.Assign(out var label),
new Image()
.Source("dotnet_bot.png")
.Assign(out var image)
.SizeRequest(100, 100)
.GestureRecognizers(new GestureRecognizer[]
{
new TapGestureRecognizer()
.NumberOfTapsRequired(2)
.OnTapped((e, args) =>
{
label.Text = "You tapped 2 times";
})
})
)
PanGestureRecognizer
sınıfı, bir görünümde sürükleme hareketlerini algılamak için kullanılır. OnPanUpdated
metodu ile sürükleme hareketi olayını işleyebilir ve görünümün konumunu güncelleyebilirsiniz.
İşte PanGestureRecognizer
kullanarak ekranda bir resmi hareket ettirme örneği:
public class PanGesturePage : ContentPage
{
double x, y;
public PanGesturePage()
{
this
.Content(
new Grid()
.Children(
new Image()
.Source("dotnet_bot.png")
.Assign(out var image)
.SizeRequest(100, 100)
.GestureRecognizers(new GestureRecognizer[]
{
new PanGestureRecognizer()
.OnPanUpdated((e, args) =>
{
switch (args.StatusType)
{
case GestureStatus.Running:
image.TranslationX = x + args.TotalX;
image.TranslationY = y + args.TotalY;
break;
case GestureStatus.Completed:
x = image.TranslationX;
y = image.TranslationY;
break;
}
})
})
)
);
}
}
PointerGestureRecognizer
sınıfı, bir görünüm üzerinde giriş, çıkış ve hareket gibi işaretçi olaylarını algılamak için kullanılır. Bu olayları işlemek ve görünümü buna göre güncellemek için OnPointerEntered
, OnPointerExited
ve OnPointerMoved
metodlarını kullanabilirsiniz.
İşte PointerGestureRecognizer
kullanarak bir resim üzerinde işaretçi konumunu gösterme örneği:
public class PointerGesturePage : ContentPage
{
public PointerGesturePage()
{
this
.Content(
new StackLayout()
.Center()
.Children(
new Label().Assign(out var label).FontSize(20),
new Label().Assign(out var enterExitLabel).FontSize(20).TextColor(Colors.Blue),
new Image()
.Source("dotnet_bot.png")
.Assign(out var image)
.SizeRequest(300, 300)
.GestureRecognizers(new GestureRecognizer[]
{
new PointerGestureRecognizer()
.OnPointerEntered((e, args) =>
{
enterExitLabel.Text = "Entered";
})
.OnPointerExited((e, args) =>
{
enterExitLabel.Text = "Exited";
})
.OnPointerMoved((e, args) =>
{
var pos = args.GetPosition(relativeTo: image).Value;
label.Text = $"point: {pos.X}, {pos.Y}";
})
})
)
};
}
}
FmgLib.MauiMarkup
, süslü parantezler içinde gradyan fırçalarını kullanarak görsel efektler oluşturmanın bir yolunu sağlar. İki tanımlı gradyan fırça türü vardır:
-LinearGradientBrush
İşte arka planı LinearGradientBrush
olan bir Border
öğesi örneği. Gradyan efekti sol üst köşeden sağ alt köşeye doğru gider.
new Border()
.Background(
new LinearGradientBrush()
.StartPoint(new Point(0, 0))
.EndPoint(new Point(1, 1))
.GradientStops(
new List<GradientStop>(){
new GradientStop(Colors.Yellow, 0.0),
new GradientStop(Colors.Red, 0.25),
new GradientStop(Colors.Blue, 0.75),
new GradientStop(Colors.LimeGreen, 1.0)
}
)
)
Grid
öğesi, Satır ve Sütun tanımlarını kullanarak karmaşık, çok satırlı ve çok sütunlu düzenler oluşturmanıza olanak tanır. Satır ve sütunların sayısını ve boyutunu sırasıyla RowDefinitions
ve ColumnDefinitions
metodları ile tanımlayabilirsiniz.
Bir çocuk öğenin grid içindeki pozisyonunu Row()
, Column()
, ColumnSpan()
ve RowSpan()
metodları ile ayarlayabilirsiniz. Bu metodlar sırasıyla Grid.Row
, Grid.Column
, Grid.ColumnSpan
ve Grid.RowSpan
bağlı özelliklerine karşılık gelir.
Satır ve sütunların sayısı ve boyutunu tanımlamak, sırasıyla RowDefinitions
ve ColumnDefinitions
metodları ile yapılır. Bu metodlar, satır veya sütunun özelliklerini tanımlayan bir lambda fonksiyonu alır.
Aşağıdaki örnekte, dört satır ve iki sütunlu bir Grid
öğesi tanımlanıyor:
new Grid()
.RowDefinitions(e => e.Star(2).Star(0.5, count: 3)))
.ColumnDefinitions(e => e.Absolute(100).Star())
.Children(
...
)
Kodun yaptığı şey şudur:
RowDefinitions
metodu, farklı boyutlarda dört satır tanımlıyor. İlk satır 2 yıldız alıyor, bu da Grid'deki diğer herhangi bir satırdan iki kat daha fazla dikey alan kaplayacağı anlamına geliyor. İkinci, üçüncü ve dördüncü satırlar her biri 0.5 yıldız alır. count parametresi isteğe bağlıdır ve Grid'e eklenecek aynı boyutta kaç satır olduğunu belirtir. Bu durumda, 0.5 yıldız boyutunda 3 satır ekler.
ColumnDefinitions
metodu iki sütun tanımlıyor. İlk sütun, Absolute
metodu kullanılarak sabit 100 piksel genişliğe ayarlanmış, ikinci sütun ise kalan alanı Star
metodu ile kaplıyor.
İşte bir grid tanımının tam bir örneği:
new Grid()
.RowDefinitions(e => e.Star(2).Star())
.ColumnDefinitions(e => e.Absolute(200).Star()))
.Children(
new BoxView().Color(Colors.Green),
new Label().Text("Column 0, Row 0"),
new BoxView().Color(Colors.Blue).Column(1).Row(0),
new Label().Text("Column 1, Row 0").Column(1).Row(0),
new BoxView().Color(Colors.Teal).Column(0).Row(1),
new Label().Text("Column 0, Row 1").Column(0).Row(1),
new BoxView().Color(Colors.Purple).Column(1).Row(1),
new Label().Text("Column 1, Row 1").Column(1).Row(1),
)
FmgLib.MauiMarkup
içinde, ITextAlignment
arayüzünü uygulayan tüm sınıflar aşağıdaki genişletme metodlarına sahip olur:
TextCenterHorizontal
TextCenterVertical
TextCenter
TextLeft
TextRight
TextBottom
TextBottomLeft
TextBottomRight
TextTop
TextTopLeft
TextTopRight
TextTopCenter
TextBottomCenter
TextCenterLeft
TextCenterRight
AlignText
Genişletme metodlarını kullanmak için, bir Label
nesnesi oluşturun (veya ITextAlignment
uygulayan herhangi bir nesne) ve istediğiniz metodu çağırın:
new Label().TextCenter()
Bu örnek, metni etiketin içerdiği öğe içinde hem yatay hem de dikey olarak merkezler.
FmgLib.MauiMarkup
içinde, her görünümü kendi içinde aşağıdaki genişletme metodlarını kullanarak düzenleyebilirsiniz:
CenterHorizontal
CenterVertical
Center
AlignLeft
AlignRight
AlignTop
AlignTopLeft
AlignTopRight
AlignBottom
AlignBottomLeft
AlignBottomRight
FillHorizontally
FillVertically
FillBothDirections
AlignTopCenter
AlignTopFill
AlignBottomCenter
AlignBottomFill
AlignCenterLeft
AlignCenterRight
AlignCenterFill
AlignFillLeft
AlignFillRight
AlignFillCenter
AlignLayout
Düzen seçeneklerini kullanmak için, bir konteyner görünümü oluşturun, düzenlemek istediğiniz görünümü konteynere ekleyin ve istediğiniz metodu çağırın:
new StackLayout()
.Children(
new Label().Text("Hello, World!").Center()
)
Bu örnekte, bir StackLayout
konteyneri içinde bir Label merkezlenmiştir. Aynı metodu diğer konteyner görünümleriyle ve içinde düzenlemek istediğiniz herhangi bir görünümle kullanabilirsiniz.
FmgLib.MauiMarkup
, UI öğeleri için özellikleri ayarlamak üzere özellikleri akıcı yardımcı metodlarla eşleştirerek kullanışlı bir yol sunar. Bu, uygulamanızın arayüzünü tanımlamayı daha kolay ve daha okunaklı hale getirir.
İşte bir Label
üzerinde özellikleri ayarlamak için akıcı metodların kullanımına bir örnek:
new Label()
.Text("This is a test")
.Padding(20)
.FontSize(30)
.Center())
FmgLib.MauiMarkup
, ayrıca cihaz kalıbına, platforma veya uygulama temasına göre özellik değerlerini ayarlama yolunu da sağlar. İşte bir Label
ın font boyutunu ve metin rengini mevcut cihaz veya temaya göre ayarlama örneği:
new Label()
.Text("Hello")
.FontSize(e => e.OnDesktop(80).OnPhone(30).Default(50))
.TextColor(e => e.OnLight(Colors.Black).OnDark(Colors.Teal))
FmgLib.MauiMarkup
, bir öğenin özelliklerini kaynağa bağlamanın basit bir yolunu sağlar, böylece kaynak değiştiğinde özellik de değişir. Bir özelliği bağlamak için akıcı metodu kullanabilirsiniz, örneğin Text()
, TextColor()
vb. ve sonra lambda ile Path()
metodunu çağırarak bağlamak istediğiniz özelliği belirtebilirsiniz.
public class SimpleBindings : ContentPage
{
public SimpleBindings()
{
this.Content(
new StackLayout()
Children(
new Slider()
.Assign(out var slider)
.Minimum(1)
.Maximum(20),
new Label()
.Text(e => e.Path("Value").Source(slider).StringFormat("Slider value: {0}"))
.FontSize(28)
)
);
}
}
Bu örnekte, bir Slider
öğesinin Value
özelliğine bağlı bir etiketin metin özelliği bulunmaktadır. Kaydırıcı değeri değiştiğinde, etiketin metni otomatik olarak yeni değeri yansıtacak şekilde güncellenir.
Bir özelliği görsel ağacın bir parçası olmayan bir nesneye de bağlayabilirsiniz. Bu, görsel bir öğeye bağlamak istediğiniz ayrı bir veri kaynağına, örneğin bir modele veya bir görünüm modeline sahip olduğunuzda faydalıdır.
FmgLib.MauiMarkup ile çoklu bağlamayı kolayca kullanabilirsiniz. e.Bindings(...) metodu ile istediğiniz kadar BindingBase ekleyebilirsiniz.
Örnek kullanım şu şekildedir:
public partial class MainPage : ContentPage, IFmgLibHotReload
{
private readonly MainPageViewModel viewModel;
public MainPage()
{
viewModel = new MainPageViewModel();
this.InitializeHotReload();
}
public void Build()
{
this
.BindingContext(viewModel)
.Content(
new VerticalStackLayout()
.Spacing(20)
.Children(
new CheckBox()
.IsChecked(e =>
e.Bindings(
new Binding().Path("Employee.IsOver16"),
new Binding().Path("Employee.HasPassedTest"),
new Binding().Path("Employee.IsSuspended").Converter(new InverterConverter())
)
.Converter(new AllTrueMultiConverter())
.FallbackValue("Is Error.")
.TargetNullValue("Is Null.")
),
new Label()
.Text(e =>
e.Bindings(
new Binding().Path("Employee.Id"),
new Binding().Path("Employee.Name"),
new Binding().Path("Employee.IsSuspended")
)
.StringFormat("{0} : {1} : {2}")
.FallbackValue("Is Error.")
.TargetNullValue("Is Null.")
)
)
);
}
}
İşte basit bir shell tabanlı uygulama örneği:
using FmgLib.MauiMarkup;
public partial class App : Application
{
public App()
{
this.MainPage(
new Shell()
.ItemTemplate(() => new ShellItemTemplate())
.Resources(AppResources.Default)
.Items(
new FlyoutItem()
.FlyoutDisplayOptions(FlyoutDisplayOptions.AsMultipleItems)
.Items(
new Tab()
.Title("Main")
.Items(
new ShellContent()
.Title("Hello Page")
.ContentTemplate(new HelloWorldPage()),
new ShellContent()
.Title("ExamplePage")
.ContentTemplate(new ExamplePage()),
),
new ShellContent()
.Title("Grid")
.ContentTemplate(new GridPage()),
...
)
)
);
}
}
FlyoutItem
'ın görünümünü özelleştirebilirsiniz, özel bir içerik görünümü tanımlayarak ve Shell
öğesinde ItemTemplate
özelliğini ayarlayarak.
İşte bir FlyoutItem
'ın görünümünü tanımlama örneği:
public class ShellItemTemplate : ContentView
{
public ShellItemTemplate()
{
this
.Content(
new Grid()
.ColumnDefinitions(e => e.Star(0.2).Star(0.8))
.Children(
new Image()
.Source(e => e.Path("FlyoutIcon"))
.Margin(5)
.HeightRequest(45),
new Label()
.GridColumn(1)
.Text(e => e.Path("Title"))
.FontSize(20)
.FontAttributes(FontAttributes.Italic)
.CenterVertically()
)
);
}
}
FmgLib.MauiMarkup
, öğelerin stillerini Style<T>
sınıfını kullanarak tanımlamanın bir yolunu sunar. İşte bir butonun stilini nasıl tanımlayacağınıza dair bir örnek:
new Style<Button>(e => e
.TextColor(e => e.OnLight(Colors.White).OnDark(AppColors.Primary))
.BackgroundColor(e => e.OnLight(AppColors.Primary).OnDark(Colors.White))
.FontFamily("OpenSansRegular")
.FontSize(14)
.CornerRadius(8)
.Padding(new Thickness(14, 10))
.MinimumHeightRequest(44)
.MinimumWidthRequest(44))
Örnekte, bir butonun özellikleri akıcı uzantı metotları kullanılarak ayarlanmaktadır.
Ayrıca, uygulama temasına, cihaz kalıbına veya platforma bağlı olarak farklı değerler de kullanabilirsiniz:
Ek olarak, öğeler için görsel durumlar tanımlayabilirsiniz:
new Style<Button>(e => e...)
{
...
new VisualState<Button> (VisualStateEnum.VisualElement.Normal, e => e
.TextColor(e => e.OnLight(Colors.White).OnDark(AppColors.Primary))
.BackgroundColor(e => e.OnLight(AppColors.Primary).OnDark(Colors.White))),
new VisualState<Button> (VisualStateEnum.VisualElement.Disabled, e => e
.TextColor(e => e.OnLight(AppColors.Gray950).OnDark(AppColors.Gray200))
.BackgroundColor(e => e.OnLight(AppColors.Gray200).OnDark(AppColors.Gray600))),
},
Ayrıca, görsel durumları animasyon tanımlamak için kullanabilirsiniz:
new Style<Button>(e => e...)
{
...
new VisualState<Button>(VisualStates.Button.Normal, e => e
.FontSize(33)
.TextColor(AppColors.Gray200))
{
async button => {
await button.RotateTo(0); // create animation inside VisualState
}
},
new VisualState<Button>(VisualStates.Button.Disabled, e => e
.FontSize(20)
.TextColor(AppColors.Gray600))
{
async button => {
await button.RotateTo(180);
}
},
}
Son olarak, tanımlanan tüm stiller bir ResourceDictionary
içine yerleştirilebilir:
new ResourceDictionary
{
...
new Style<Button>(e => e
.TextColor(e => e.OnLight(Colors.White).OnDark(AppColors.Primary))
.BackgroundColor(e => e.OnLight(AppColors.Primary).OnDark(Colors.White))
.FontFamily("OpenSansRegular")
.FontSize(14)
.CornerRadius(8)
.Padding(new Thickness(14,10))
.MinimumHeightRequest(44)
.MinimumWidthRequest(44))
{
new VisualState<Button> (VisualStateEnum.VisualElement.Normal, e => e
.TextColor(e => e.OnLight(Colors.White).OnDark(AppColors.Primary))
.BackgroundColor(e => e.OnLight(AppColors.Primary).OnDark(Colors.White))),
new VisualState<Button> (VisualStateEnum.VisualElement.Disabled, e => e
.TextColor(e => e.OnLight(AppColors.Gray950).OnDark(AppColors.Gray200))
.BackgroundColor(e => e.OnLight(AppColors.Gray200).OnDark(AppColors.Gray600)))
},
new Style<Frame>(e => e
.HasShadow(false)
.BorderColor(e => e.OnLight(AppColors.Gray200).OnDark(AppColors.Gray950))
.CornerRadius(8)),
...
};
FmgLib: mauiMarkup
içinde, kendi genişletme metodlarınızı statik bir sınıf içinde statik bir metot tanımlayarak oluşturabilirsiniz.
İşte bir Label nesnesinin yazı tipi boyutunu ayarlayan genişletme metodlarına bir örnek:
public static T FontSize<T>(this T self,
double fontSize)
where T : Microsoft.Maui.Controls.Label
{
self.SetValue(Microsoft.Maui.Controls.Label.FontSizeProperty, fontSize);
return self;
}
public static T FontSize<T>(this T self, Func<PropertyContext<double>, IPropertyBuilder<double>> configure)
where T : Microsoft.Maui.Controls.Label
{
var context = new PropertyContext<double>(self, Microsoft.Maui.Controls.Label.FontSizeProperty);
configure(context).Build();
return self;
}
public static SettersContext<T> FontSize<T>(this SettersContext<T> self,
double fontSize)
where T : Microsoft.Maui.Controls.Label
{
self.XamlSetters.Add(new Setter { Property = Microsoft.Maui.Controls.Label.FontSizeProperty, Value = fontSize });
return self;
}
public static SettersContext<T> FontSize<T>(this SettersContext<T> self, Func<PropertySettersContext<double>, IPropertySettersBuilder<double>> configure)
where T : Microsoft.Maui.Controls.Label
{
var context = new PropertySettersContext<double>(self.XamlSetters, Microsoft.Maui.Controls.Label.FontSizeProperty);
configure(context).Build();
return self;
}
public static Task<bool> AnimateFontSizeTo<T>(this T self, double value, uint length = 250, Easing? easing = null)
where T : Microsoft.Maui.Controls.Label
{
double fromValue = self.FontSize;
var transform = (double t) => Transformations.DoubleTransform(fromValue, value, t);
var callback = (double actValue) => { self.FontSize = actValue; };
return Transformations.AnimateAsync<double>(self, "AnimateFontSizeTo", transform, callback, length, easing);
}
Bu, aşağıdaki kullanımı sağlar:
new Label().FontSize(28)
veya:
new Label().FontSize(e => e.Path("MyFontSize").Source(myModel))
new Label().FontSize(e => e.OnPhone(30).OnTablet(50).Default(40))
veya bir stil bağlamında kullanım:
new Style<Label>(e => e
.FontSize(20)
.CenterVertically()
.CenterHorizontally())
veya bir animasyon bağlamında kullanım.
Tetikleyiciler, belirli koşullar veya olaylara yanıt olarak özellikleri ayarlamanıza olanak tanır.
Bir özellik tetikleyicisi, başka bir özelliğin değerindeki değişikliğe yanıt olarak bir özelliği ayarlar.
İşte bir Entry
öğesinin odaklandığında arka plan rengini ve metin rengini değiştirmek için bir özellik tetikleyicisini kullanma örneği:
using FmgLib:mauiMarkup;
public class PropertyTriggerPage : ContentPage
{
public PropertyTriggerPage()
{
this
.Resources(
new ResourceDictionary
{
new Style<Entry>
{
Entry.BackgroundColorProperty.Set(Colors.Black),
Entry.TextColorProperty.Set(Colors.White),
new Trigger(typeof(Entry))
.Property(Entry.IsFocusedProperty)
.Value(true)
.Setters(
new Setters<Entry>(e => e
.BackgroundColor(Colors.Yellow)
.TextColor(Colors.Black))
),
}
}
)
.Content(
new StackLayout()
.Children(
new Entry().Text("Enter name"),
new Entry().Text("Enter password"),
new Entry().Text("Enter address")
)
);
}
}
Bir veri tetikleyicisi, bir veri kaynağının değerindeki bir değişikliğe yanıt olarak bir özelliği ayarlar.
İşte bir Entry
öğesinin metin uzunluğu sıfır olduğunda bir düğmeyi devre dışı bırakmak için bir veri tetikleyicisini kullanma örneği:
this.Content(new StackLayout()
.Children(
new Entry().Assign(out var entry).Text("Enter text..."),
new Button()
.Text("Save")
.Triggers(
new DataTrigger(typeof(Button))
.Binding(e => e.Path("Text.Length").Source(entry))
.Value(0)
.Setters(new Setters<Entry>(e => e.IsEnabled(false)))
),
)
)
Bir olay tetikleyicisi, bir olaya yanıt olarak bir özelliği ayarlar.
İşte bir Entry
öğesinin girdisini bir sayı olarak doğrulamak için bir olay tetikleyicisini kullanma örneği:
this
.Content(new StackLayout()
.Children(
new Entry()
.Assign(out var entry)
.Text("Enter text...")
.Triggers(
new EventTrigger()
.Event("TextChanged")
.Actions(new NumericValidationTriggerAction())
)
)
)
Ve işte NumericValidationTriggerAction
sınıfının tanımı:
public class NumericValidationTriggerAction : TriggerAction<Entry>
{
protected override void Invoke(Entry entry)
{
double result;
bool isValid = Double.TryParse(entry.Text, out result);
entry.TextColor = isValid ? Colors.Black : Colors.Red;
}
}
FmgLib.MauiMarkup kütüphanesi, üçüncü taraf kütüphanelerinden kontrol tipleri için de uzantı metotları üretebilir. Bunu başarmak için, FmgLib.MauiMarkup tarafından sağlanan MauiMarkupAttribute
kullanılmalıdır.
Uzantı metotları oluşturmak istediğiniz kontrolü [MauiMarkup(typeof(YourControl))]
şeklinde belirtin.
MauiMarkup()
özniteliğinin yapıcı metodu, argüman olarak verilen tip içinde bulunan BindableProperties ve Eventler için otomatik olarak uzantı metotları üretir. Yapıcı metod içinde minimum 1 tür sağlayabilirsiniz ve maksimum sınır yoktur. Tek bir sınıfa birden fazla MauiMarkup özniteliği eklenebilir.
NOT: Diyelim ki Fluent Metod oluşturmak istediğiniz bir sınıfın içinde miras alınan sınıflarda bulunan bir özellik new
anahtar kelimesi ile tekrardan eklenmişse yeni olaşacak Fluent Metod ismi PropertName + New
şeklinde olacaktır.
Örneğin SfAvatarView sınıfı içinde Background özelliği new ile yeniden yazıldığı için VisualElement içindeki Background ile aynı olduğundan hata oluşmaması için SfAvatarView sınıfına ait Background özelliği için fluent metod adı BackgroundNew
şekline olacaktır.
Örneklere bir göz atalım:
using FmgLib.MauiMarkup;
namespace GeneratedExam;
[MauiMarkup(typeof(ZXing.Net.Maui.Controls.BarcodeGeneratorView))]
public class MyBarcodeGeneratorView { }
[MauiMarkup(typeof(ZXing.Net.Maui.Controls.CameraView))]
public class MyCameraView { }
[MauiMarkup(typeof(ZXing.Net.Maui.Controls.CameraBarcodeReaderView))]
public class MyCameraBarcodeReaderView { }
[MauiMarkup(typeof(SkiaSharp.Extended.UI.Controls.SKLottieView))]
public class MySkLottieView { }
Veya bunun yerine şöyle kullanılabilir:
using Microsoft.Extensions.Logging;
using FmgLib.MauiMarkup;
using SkiaSharp.Extended.UI.Controls;
using ZXing.Net.Maui.Controls;
using UraniumUI.Material.Controls;
namespace MauiApp1
{
[MauiMarkup(typeof(CameraView))]
[MauiMarkup(typeof(SKLottieView), typeof(SKFileLottieImageSource), typeof(DataGrid))]
[MauiMarkup(typeof(SKConfettiView), typeof(BarcodeGeneratorView),typeof(InputField),typeof(EditorField),typeof(TextField))]
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
#if DEBUG
builder.Logging.AddDebug();
#endif
return builder.Build();
}
}
}
ZXing.Net.Maui.Controls kütüphanesinden CameraView sınıfı:
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
using System;
namespace ZXing.Net.Maui.Controls
{
public partial class CameraView : View, ICameraView
{
public event EventHandler<CameraFrameBufferEventArgs> FrameReady;
void ICameraFrameAnalyzer.FrameReady(CameraFrameBufferEventArgs e)
=> FrameReady?.Invoke(this, e);
public static readonly BindableProperty IsTorchOnProperty =
BindableProperty.Create(nameof(IsTorchOn), typeof(bool), typeof(CameraView), defaultValue: true);
public bool IsTorchOn
{
get => (bool)GetValue(IsTorchOnProperty);
set => SetValue(IsTorchOnProperty, value);
}
public static readonly BindableProperty CameraLocationProperty =
BindableProperty.Create(nameof(CameraLocation), typeof(CameraLocation), typeof(CameraView), defaultValue: CameraLocation.Rear);
public CameraLocation CameraLocation
{
get => (CameraLocation)GetValue(CameraLocationProperty);
set => SetValue(CameraLocationProperty, value);
}
public void AutoFocus()
=> StrongHandler?.Invoke(nameof(AutoFocus), null);
public void Focus(Point point)
=> StrongHandler?.Invoke(nameof(Focus), point);
CameraViewHandler StrongHandler
=> Handler as CameraViewHandler;
}
}
MauiMarkup özniteliği kullanılarak oluşturulan CameraViewExtension sınıfı aşağıdaki gibi olacaktır:
//
// <auto-generated-fmglib-mauimarkup-generator />
//
namespace FmgLib.MauiMarkup;
public static partial class CameraViewExtension
{
public static T CameraLocation<T>(this T self,
ZXing.Net.Maui.CameraLocation cameraLocation)
where T : ZXing.Net.Maui.Controls.CameraView
{
self.SetValue(ZXing.Net.Maui.Controls.CameraView.CameraLocationProperty, cameraLocation);
return self;
}
public static T CameraLocation<T>(this T self, Func<PropertyContext<ZXing.Net.Maui.CameraLocation>, IPropertyBuilder<ZXing.Net.Maui.CameraLocation>> configure)
where T : ZXing.Net.Maui.Controls.CameraView
{
var context = new PropertyContext<ZXing.Net.Maui.CameraLocation>(self, ZXing.Net.Maui.Controls.CameraView.CameraLocationProperty);
configure(context).Build();
return self;
}
public static SettersContext<T> CameraLocation<T>(this SettersContext<T> self,
ZXing.Net.Maui.CameraLocation cameraLocation)
where T : ZXing.Net.Maui.Controls.CameraView
{
self.XamlSetters.Add(new Setter { Property = ZXing.Net.Maui.Controls.CameraView.CameraLocationProperty, Value = cameraLocation });
return self;
}
public static SettersContext<T> CameraLocation<T>(this SettersContext<T> self, Func<PropertySettersContext<ZXing.Net.Maui.CameraLocation>, IPropertySettersBuilder<ZXing.Net.Maui.CameraLocation>> configure)
where T : ZXing.Net.Maui.Controls.CameraView
{
var context = new PropertySettersContext<ZXing.Net.Maui.CameraLocation>(self.XamlSetters, ZXing.Net.Maui.Controls.CameraView.CameraLocationProperty);
configure(context).Build();
return self;
}
public static T IsTorchOn<T>(this T self,
bool isTorchOn)
where T : ZXing.Net.Maui.Controls.CameraView
{
self.SetValue(ZXing.Net.Maui.Controls.CameraView.IsTorchOnProperty, isTorchOn);
return self;
}
public static T IsTorchOn<T>(this T self, Func<PropertyContext<bool>, IPropertyBuilder<bool>> configure)
where T : ZXing.Net.Maui.Controls.CameraView
{
var context = new PropertyContext<bool>(self, ZXing.Net.Maui.Controls.CameraView.IsTorchOnProperty);
configure(context).Build();
return self;
}
public static SettersContext<T> IsTorchOn<T>(this SettersContext<T> self,
bool isTorchOn)
where T : ZXing.Net.Maui.Controls.CameraView
{
self.XamlSetters.Add(new Setter { Property = ZXing.Net.Maui.Controls.CameraView.IsTorchOnProperty, Value = isTorchOn });
return self;
}
public static SettersContext<T> IsTorchOn<T>(this SettersContext<T> self, Func<PropertySettersContext<bool>, IPropertySettersBuilder<bool>> configure)
where T : ZXing.Net.Maui.Controls.CameraView
{
var context = new PropertySettersContext<bool>(self.XamlSetters, ZXing.Net.Maui.Controls.CameraView.IsTorchOnProperty);
configure(context).Build();
return self;
}
public static T OnFrameReady<T>(this T self, System.EventHandler<ZXing.Net.Maui.CameraFrameBufferEventArgs> handler)
where T : ZXing.Net.Maui.Controls.CameraView
{
self.FrameReady += handler;
return self;
}
public static T OnFrameReady<T>(this T self, System.Action<T> action)
where T : ZXing.Net.Maui.Controls.CameraView
{
self.FrameReady += (o, arg) => action(self);
return self;
}
}
Örneğin, TextField ve SKLottieView Kontrolleri için örnek kodları yazalım:
new TextField()
.Title("Password")
.TitleColor(Colors.LightGray)
.AccentColor(Colors.CadetBlue)
.TextColor(Colors.White)
.IsPassword(true),
new SKLottieView()
.Source(new SKFileLottieImageSource().File("iconapp.json"))
.RepeatCount(-1)
.HeightRequest(250)
.WidthRequest(250)
MauiMarkupAttachedPropAttribute sayesinde üçüncü taraf kütüphanelerdeki Control sınıfları içinde AttachedProperty'lerin rahatlıkla extension methodlarını oluşturabilirsiniz.
Yapıcı Methodu içerisindeki ilk parametre Control sınıfı tipini, ikinci parametre AttachedProperty adını, üçüncü parametre
ttachedProperty'in alabileceği değer tipini ve dördüncü parametre ise AttachedProperty'in hangi türe uygulanacağını alır.
Örnek kullanım:
[MauiMarkupAttachedProp(typeof(InputKit.Shared.Controls.FormView), nameof(InputKit.Shared.Controls.FormView.IsSubmitButtonProperty), typeof(bool), typeof(Button))]
[MauiMarkup(typeof(InputKit.Shared.Controls.FormView))]
public class MyFormView { }
Veya
using Microsoft.Extensions.Logging;
using FmgLib.MauiMarkup;
namespace MauiApp1
{
[MauiMarkupAttachedProp(typeof(InputKit.Shared.Controls.FormView), nameof(InputKit.Shared.Controls.FormView.IsSubmitButtonProperty), typeof(bool), typeof(Button))]
[MauiMarkup(typeof(InputKit.Shared.Controls.FormView))]
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
#if DEBUG
builder.Logging.AddDebug();
#endif
return builder.Build();
}
}
}
Button sınıfında AttachedProperty'in kullanımı ise şu şekilde olacaktır:
new Button()
.Text("Login")
.FontAttributes(Bold)
.FormViewIsSubmitButton(true)
MauiProgram.cs dosyasına aşağıdaki kod eklenmelidir:
builder
.UseMauiApp<App>()
.UseMauiMarkupLocalization();
Ana projenizde json türünde bir dil dosyasına sahip olmalısınız. Çeviri bu dosyadan okunarak içe aktarılacaktır.
Eğer dosya(lar) için parametrelerde bir yol belirtmezseniz (
builder
.UseMauiApp<App>()
.UseMauiMarkupLocalization();
//.UseMauiMarkupLocalization(defaultLang:"en-US"); // veya
//.UseMauiMarkupLocalization(defaultLang:"en-US", "Loc1.json", "Loc2.json"); // veya
), ana dizinde Localization.json
adlı bir json dosyası arayacaktır.
Eğer şu şekilde bir veya daha fazla parametre verirseniz:
builder
.UseMauiApp<App>()
.UseMauiMarkupLocalization("Localization1.json", "Localization2.json", "/Languages/Temp1.json");
Belirtilen dosya yollarındaki json dosyalarını okuyacaktır.
Burada kritik nokta, json dosyaları için Build Action: MauiAsset
seçeneğini belirlemektir.
Doğru json formatı şu şekildedir:
{
"Hello": {
"tr-TR": "Merhaba Dünya!",
"en-US": "Hello World!"
},
"Msg": {
"tr-TR": "Deneme amaçlı yapılmıştır.",
"en-US": "It was made for testing purposes."
}
}
‘Msg’ anahtar kelimeleri yerine istediğiniz kelimeyi veya kelime öbeğini kullanabilirsiniz. Herhangi bir Regex sınırlamanız yoktur.
Ayrıca, ‘tr-TR’ ve ‘en-US’ dil anahtarlarını istediğiniz kelimeler veya cümlelerle değiştirebilirsiniz. Ancak ‘en-US’, ‘tr-TR’, ‘fr-FR’ gibi ifadelerin kullanılması tavsiye edilir.
Kodu şu şekilde basitçe kullanabilirsiniz:
new Label()
.Text(e => e.Translate("Hello"))
.FontSize(32)
.CenterHorizontal()
.SemanticHeadingLevel(SemanticHeadingLevel.Level1),
new Label()
.Text(e => e.Translate("Msg"))
.FontSize(18)
.CenterHorizontal()
.SemanticDescription(e => e.Translate("Msg"))
.SemanticHeadingLevel(SemanticHeadingLevel.Level1)
Mevcut dili değiştirmek için şu adımları takip edebilirsiniz:
Translator.Instance.ChangeCulture(CultureInfo.GetCultureInfo("en-US"));
//OR
Translator.Instance.ChangeCulture(CultureInfo.GetCultureInfo("tr-TR"));
MauiProgram.cs dosyasında,
builder
.UseMauiApp<App>()
.UseMauiMarkupLocalizationWithResx(AppResources.ResourceManager);
// .UseMauiMarkupLocalizationWithResx(AppResources.ResourceManager, "en-US"); // varsayılan dili ayarla
ifadesi eklenmelidir.
Projenizde .resx
uzantılı kaynak dosyaları bulunmalıdır. Çeviriler bu dosyalardan okunup içe aktarılacaktır.
Ardından, MauiProgram.cs içinde ResourceManager
değerini UseMauiMarkupLocalizationWithResx
parametresi olarak geçirin.
‘tr-TR’ ve ‘en-US’ dil anahtarlarını istediğiniz kelime veya cümlelerle değiştirebilirsiniz. Ancak ‘en-US’, ‘tr-TR’, ‘fr-FR’ gibi ifadelerin kullanılması önerilir.
Sistemin dilini aşağıdaki ifadeyle değiştirebilirsiniz: TranslatorResx.Instance.ChangeCulture(CultureInfo.GetCultureInfo("en-US"));
Kodda aşağıdaki şekilde kullanabilirsiniz:
new Label()
.Text(e => e.TranslateResx("Merhaba"))
.FontSize(32)
.CenterHorizontal()
.SemanticHeadingLevel(SemanticHeadingLevel.Level1),
new Label()
.Text(e => e.TranslateResx(nameof(AppResource.Msg)))
.FontSize(18)
.CenterHorizontal()
.SemanticDescription(e => e.TranslateResx("Msg"))
.SemanticHeadingLevel(SemanticHeadingLevel.Level1),
new VerticalStackLayout()
.Center()
.Children(
new RadioButton()
.IsChecked(TranslatorResx.Instance.CurrentCulture.Name == "tr-TR")
.Content("tr-TR")
.OnCheckedChanged((sender, e) =>
{
TranslatorResx.Instance.ChangeCulture(CultureInfo.GetCultureInfo("tr-TR"));
}),
new RadioButton()
.IsChecked(TranslatorResx.Instance.CurrentCulture.Name == "en-US")
.Content("en-US")
.OnCheckedChanged((sender, e) =>
{
TranslatorResx.Instance.ChangeCulture(CultureInfo.GetCultureInfo("en-US"));
})
)
using Microsoft.Maui.Layouts;
using FmgLib.MauiMarkup;
namespace MyOrderApp.Views;
public partial class HomePage : BasePage<HomePageViewModel>
{
public HomePage(HomePageViewModel viewModel) : base(viewModel, "Home Page")
{
}
public override void Build()
{
this
.Content(
new VerticalStackLayout()
.Padding(10)
.Children(
new SearchBar()
.Placeholder("Ürünlerde Ara.")
.Margin(10)
.Assign(out var search)
.SearchCommand(BindingContext.SearchCommand)
.Bind(SearchBar.SearchCommandParameterProperty, "Text", source: search),
new Frame()
.CornerRadius(15)
.BackgroundColor(Colors.Blue)
.BorderColor(Colors.Blue)
.HeightRequest(150)
.Margin(15,7)
.Padding(0)
.Content(
new Grid()
.ColumnDefinitions(e => e.Star(5).Star(5))
.RowDefinitions(e => e.Star(5).Star(5))
.Children(
new Frame()
.Row(0)
.Column(0)
.Margin(0,20,0,0)
.Padding(0)
.CornerRadius(0)
.BackgroundColor(Colors.DarkBlue)
.BorderColor(Colors.DarkBlue)
.Content(
new Label()
.Text("%50 İndirim")
.TextColor(Colors.White)
.FontAttributes(FontAttributes.Bold)
.FontSize(20)
.Center()
),
new Label()
.Text("Tüm Unlu Mamüllerde her gün saat 21:00'dan sonra!")
.FontSize(12)
.Row(1)
.Column(0)
.TextColor(Colors.White)
.FontAttributes(FontAttributes.Italic)
.Margin(10,3,0,0),
new Image()
.Source("white_board.png")
.Row(0)
.Column(1)
.RowSpan(2)
.SizeRequest(150,100)
.Opacity(.8)
)
),
new Grid()
.ColumnDefinitions(e => e.Star(7).Star(3))
.FillHorizontal()
.Padding(10)
.Children(
new Label()
.Text("Son Ürünler")
.FontAttributes(FontAttributes.Bold)
.FontSize(18)
.CenterVertical()
.Column(0)
.AlignLeft(),
new Label()
.Text("Tümünü Gör")
.FontSize(15)
.CenterVertical()
.Column(1)
.AlignRight()
.TextDecorations(TextDecorations.Underline)
.GestureRecognizers(
new TapGestureRecognizer()
.Command(BindingContext.GotoAllProductsCommand)
)
),
new CollectionView()
.SelectionMode(SelectionMode.None)
.Bind(CollectionView.ItemsSourceProperty, "Products")
.ItemsLayout(new LinearItemsLayout(ItemsLayoutOrientation.Horizontal).ItemSpacing(10))
.EmptyView(
new VerticalStackLayout()
.Children(
new Label()
.Text("Kayıt Yoktur.")
.TextColor(Colors.Red)
.FontAttributes(FontAttributes.Bold)
.FontSize(18)
)
.Center()
)
.ItemTemplate(() =>
new Frame()
.CornerRadius(15)
.BorderColor(Colors.LightGray)
.BackgroundColor(Colors.LightGray)
.MinimumHeightRequest(200)
.MaximumWidthRequest(200)
.Padding(5)
.Content(
new Grid()
.RowDefinitions(e => e.Star(1).Star(6).Star(2).Star(1))
.Padding(5)
.Children(
new Grid()
.Row(0)
.ColumnDefinitions(e => e.Star(6).Star(4))
.Children(
new ImageButton()
.Bind(ImageButton.SourceProperty, nameof(ProductVM.IsFavorite), converter: new BoolToFavoriteImageConverter())
.BackgroundColor(Colors.Transparent)
.AlignLeft()
.SizeRequest(30, 30)
.Command(BindingContext.ChangeFavoriteCommand)
.Bind(ImageButton.CommandParameterProperty, "."),
new Frame()
.CornerRadius(20)
.HeightRequest(25)
.WidthRequest(50)
.Padding(0)
.BackgroundColor(Colors.Red)
.BorderColor(Colors.Red)
.Column(1)
.Bind(Microsoft.Maui.Controls.Frame.IsVisibleProperty, nameof(ProductVM.IsDiscount))
.Content(
new Label()
.Bind(Label.TextProperty, nameof(ProductVM.DiscountRate))
.FontSize(11)
.FontAttributes(FontAttributes.Bold)
.TextColor(Colors.White)
.Center()
)
),
new Image()
.Bind(Image.SourceProperty, nameof(ProductVM.Image))
.SizeRequest(80,80)
.Row(1)
.CenterHorizontal(),
new VerticalStackLayout()
.Row(2)
.Children(
new Label()
.Bind(Label.TextProperty, nameof(ProductVM.Name))
.FontAttributes(FontAttributes.Bold)
.FontSize(11)
.AlignLeft()
.LineBreakMode(LineBreakMode.TailTruncation)
.FontAutoScalingEnabled(true),
new HorizontalStackLayout()
.Spacing(2)
.Children(
new Label()
.Bind(Label.TextProperty, nameof(ProductVM.Price))
.Bind(Label.TextDecorationsProperty, nameof(ProductVM.IsDiscount), converter: new BoolToTextDecorationConverter())
.Bind(Label.FontSizeProperty, nameof(ProductVM.IsDiscount), converter: new BoolToFontSizeConverter())
.FontAttributes(FontAttributes.Bold)
.CenterVertical(),
new Label()
.TextColor(Colors.Red)
.FontAttributes(FontAttributes.Bold)
.CenterVertical()
.Bind(Label.IsVisibleProperty, nameof(ProductVM.IsDiscount))
.Bind(Label.TextProperty, nameof(ProductVM.DiscountPrice)),
new Label()
.Text("/")
.FontSize(10)
.CenterVertical()
.TextColor(Colors.DarkSlateGray),
new Label()
.FontSize(10)
.CenterVertical()
.TextColor(Colors.DarkSlateGray)
.Bind(Label.TextProperty, nameof(ProductVM.Unit))
)
),
new Button()
.Row(3)
.Margin(new Thickness(0,5,0,0))
.Padding(0)
.Text("Sepete Ekle")
.BackgroundColor(Colors.Green)
.FontSize(12)
.FontAttributes(FontAttributes.Bold)
.CenterHorizontal()
.HeightRequest(35)
.WidthRequest(100)
.Command(BindingContext.AddProductBasketCommand)
.Bind(Button.CommandParameterProperty, ".")
)
)
),
new Grid()
.ColumnDefinitions(e => e.Star(7).Star(3))
.FillHorizontal()
.Padding(10)
.Children(
new Label()
.Text("Kategoriler")
.FontAttributes(FontAttributes.Bold)
.FontSize(18)
.CenterVertical()
.Column(0)
.AlignLeft(),
new Label()
.Text("Tümünü Gör")
.FontSize(15)
.CenterVertical()
.Column(1)
.AlignRight()
.TextDecorations(TextDecorations.Underline)
.GestureRecognizers(
new TapGestureRecognizer()
.Command(BindingContext.GotoAllCategoriesCommand)
)
),
new FlexLayout()
.ItemsSources(BindingContext.Categories)
.Assign(out var flex)
.Wrap(FlexWrap.Wrap)
.FlexBasis(FlexBasis.Auto)
.ItemTemplates(new DataTemplate(() =>
new Frame()
.CornerRadius(15)
.BorderColor(Colors.LightGray)
.BackgroundColor(Colors.LightGray)
.MinimumHeightRequest(30)
.WidthRequest(180)
.Padding(0)
.Margin(new Thickness(1,0,5,5))
.FlexBasis(FlexBasis.Auto)
.Content(
new Grid()
.ColumnDefinitions(e => e.Star(3).Star(7))
.Padding(5)
.Children(
new Image()
.Bind(Image.SourceProperty, nameof(SubCategoryVM.Icon))
.SizeRequest(30,30)
.Column(0)
.CenterVertical(),
new Label()
.Bind(Label.TextProperty, nameof(SubCategoryVM.Name))
.TextColor(Colors.CornflowerBlue)
.FontAttributes(FontAttributes.Bold)
.FontSize(12)
.Column(1)
.FontAutoScalingEnabled(true)
.CenterVertical()
)
)
))
)
.FillHorizontal()
);
}
}