الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

Wpf Layout - Part 2

بدأه HassanAlattas في 21 أغسطس 2009 · 6 رد · 2,024 مشاهدة · في Microsoft Visual C#.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

في الجزء الأول ، قمنا بالقاء نظرة سريعة على عملية التخطيط (Layout) في WPF وشرحنا طريقة استخدام احد الألواح هو الـ StackPanel، بإذنه تعالى ، في هذا الجزء سوف نحاول ان نكمل شرح بقية الألواح.

استخدام WrapPanel:

يقوم اللوح WrapPanel بترتيب العناصر في صفوف او اسطر افقية او رأسية . فيتم ملئ السطر الأول ثم السطر الثاني وهكذا.

واتجاه الترتيب يتم تحديده بواسطة الخاصية Orientation التي تكون قيمتها Horizontal بشكل افتراضي ويمكن تغييرها إلى القيمة Vertical

مثال :

<WrapPanel>
		<Button>Button 1</Button>
		<Button>Button 2</Button>
		<Button>Button 3</Button>
		<Button>Button 4</Button>
		<Button>Button 5</Button>
</WrapPanel>

النتيجة:

post-173477-1250885901_thumb.jpg

لاحظ كيف يتغير ترتيب العناصر عند تكبير وتصغير النافذة

لنأخذ مثالا آخر ، مع التغيير في بعض خصائص العناصر.

مثال :

<Window x:Class="LayoutPanels.WrapPanelExample2"
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	Title="WrapPanelExample2" Height="300" Width="300">
	<WrapPanel Margin="3">
		<Button VerticalAlignment="Top">Top Button</Button>
		<Button MinHeight="60">Tall Button 2</Button>
		<Button VerticalAlignment="Bottom">Bottom Button</Button>
		<Button>Stretch Button</Button>
		<Button VerticalAlignment="Center">Centered Button</Button>
	</WrapPanel>
</Window>

النتيجة:

post-173477-1250885953_thumb.jpg

كما هو مبين اعلاه، يكون ارتفاع كل صف بارتفاع العنصر الأكبر بداخله.

استخدام DockPanel

في الكثير من التطبيقات (مثل وورد، اكسل ...الخ) نجد شريط الأدوات قد تم رصفه في اعلى النافذة ، بينما شريط الحالة في اسفل النافذة. في WPF يمكننا عمل مثل هذا التخطيط عن طريق DockPanel التي تقوم برصف العناصر إلى اي جانب من جوانب النافذة ، وتحديد الجانب المطلوب يتم عن طريق الخاصية المرفقة DockPanel.Dock التي يمكن ان تأخذ قيمة من القيم التالية (Left، Top، Right، Bottom) .

المثال التالي يقوم بوضع زر على كل جانب :

<Window x:Class="LayoutPanels.DockPanelExample1"
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	Title="DockPanelExample1" Height="300" Width="300">
	<DockPanel>
		<Button DockPanel.Dock="Top">الزر - اعلى</Button>
		<Button DockPanel.Dock="Bottom">الزر-اسفل</Button>
		<Button DockPanel.Dock="Left">الزر- يسار</Button>
		<Button DockPanel.Dock="Right">الزر- يمين</Button>
		<Button>المساحة المتبقية</Button>
	</DockPanel>
</Window>

النتيجة:

post-173477-1250886030_thumb.png

لاحظ ان المساحة المتبقية قد تم اعطائها للزر الأخير وهذا بسبب ان الخاصية LastChildFill في DockPanel تكون قيمتها True بشكل افتراضي- ويمكنك تغيير قيمتها إذا لم يكن هذا مناسب بالنسبة لك.

تذكر ايضاً ان ترتيب العناصر يلعب دورا هاما عند التعامل مع DockPanel، فلو عدنا إلى المثال السابق ، سوف نجد ان الزرين الأعلى والأسفل قد احتل كل منهما المساحة الكاملة من الجانب المطلوب.بينما الزرين الأيمن والأيسر قد شغلا المساحة المتبقية من الجانب. وسبب هذا اننا وضعنا الزرين الأعلى والأسفل قبل الزرين الأيمن والأيسر. والنتيجة سوف تتغير عندما نقوم بتغيير الترتيب بحيث نضع الزرين الأيمن والأيسر اولاً:

post-173477-1250886149_thumb.png

يمكننا ايضاً رصف اكثر من عنصر في نفس الجانب ، وتحديد الهامش او المحاذاة سواء الأفقية او الرأسية لأي عنصر:

<Window x:Class="LayoutPanels.DockPanelExample2"
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	Title="DockPanelExample2" Height="300" Width="300">
	<DockPanel LastChildFill="True">
		<Button DockPanel.Dock="Top">زر- اعلى - ممتد</Button>
		<Button DockPanel.Dock="Top" HorizontalAlignment="Center">
			زر- اعلى- توسيط</Button>
		<Button DockPanel.Dock="Top" HorizontalAlignment="Left">
			زر-اعلى- محاذي لليسار</Button>
		<Button DockPanel.Dock="Bottom">زر- اسفل</Button>
		<Button DockPanel.Dock="Left">زر-يسار</Button>
		<Button DockPanel.Dock="Right">زر- يمين</Button>
		<Button>المساحة المتبقية</Button>
	</DockPanel>
</Window>

post-173477-1250886207_thumb.png

[وسط]لا اله الا انت سبحانك انى كنت من الظالمين

[/وسط]

#2

التداخل في الألواح:

كما ذكرنا سابقاً انه يمكن لأي لوح ان يحتوي على لوح آخر ، ويقوم اللوح الأب بالتعامل مع اللوح الأبن بنفس الطريقة التي يتعامل بها مع اي عنصر ابن آخر.

واستخدام اكثر من لوح هو امر شائع في WPF من اجل إنشاء التخطيط المطلوب، فعلى سبيل المثال لو اردنا إنشاء مربع حوار يتكون من زرين موافق والغاء الأمر يكونان في الأسفل ومربع نص يشغل المساحة المتبقية في النافذة فإننا نستخدم:

<DockPanel LastChildFill="True">
		<StackPanel DockPanel.Dock="Bottom" HorizontalAlignment="Right" Orientation="Horizontal">
			<Button Margin="10,10,2,10" Padding="3">OK</Button>
			<Button Margin="2,10,10,10" Padding="3">Cancel</Button>
		</StackPanel>
		<TextBox DockPanel.Dock="Top" Margin="10">This is a test.</TextBox>
	</DockPanel>

النتيجة

post-173477-1250886392_thumb.png

استخدام Grid:

يعتبر هذا اللوح من افضل الألواح على الأطلاق ويمكننا بواسطته عمل كل شئ يقوم به اي لوح آخر(تقريباً).

يقوم هذا اللوح بتقسيم المساحة المعطاة له إلى صفوف واعمدة غير مرئية ، ويمكن وضع العناصر داخل الخلايا (الناتجة من تقاطع الصف مع العمود) . والجميل هنا انه يمكن وضع اكثر من عنصر في نفس الخلية، وبشكل افتراضي كل Grid يتكون من صف واحد وعمود واحد ، ما يعني بانه يتكون من خلية واحدة بشكل افتراضي.

من اجل اضافة الصفوف و الأعمدة إلى Grid ، فإن علينا استخدام الخاصيتين Grid.RowDefinitions و Grid.ColumnDefinitions ، فلو اردنا اضافة صفين وثلاثة اعمدة فإننا نستخدم:

<Grid>
  <Grid.RowDefinitions>
	 <RowDefinition/>
	 <RowDefinition/>
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
	 <ColumnDefinition/>
	 <ColumnDefinition/>
	 <ColumnDefinition/>
  </Grid.ColumnDefinitions>
</Grid>

تكون الصفوف متساوية في الأرتفاع ، والأعمدة متساوية في العرض بشكل افتراضي.

ملاحظة:

لاحظ انه يجب استخدام العنصر Grid.RowDefinitions ، والعنصر Grid.ColumnDefinitions من اجل تحديد الصفوف والأعمدة المطلوبة. تسمى هذه الصيغة في Xaml بـ "صيغة العنصر الخاصية" (Property Element Syntax) وهي طريقة اخرى لتعيين الخصائص في الكائن إلى جانب "صيغة الواصفة" (Attribute Syntax) .

بعد ذلك يمكننا إضافة العناصر إلى Grid وتحديد الصف والعمود الذي يقع فيه كل عنصر عن طريق الخصائص المرفقة Grid.Row و Grid.Column:

<Grid>
………
	<Button Grid.Row="0" Grid.Column="0">Top Left</Button>
	<Button Grid.Row="0" Grid.Column="1">Middle Left</Button>
	<Button Grid.Row="1" Grid.Column="2">Bottom Right</Button>
	<Button Grid.Row="1" Grid.Column="1">Bottom Middle</Button>
………
</Grid>

الصفوف والأعمدة في Grid ترقم على الأساس الصفري ، بمعنى ان الصف الأول يكون رقمه 0 والصف الثاني يكون رقمه 1 وهكذا.

إذا لم نقم بتحديد الصف او العمود لعنصر معين فإن هذا العنصر يتم وضعه في الصف الأول والعمود الأول ، بسبب ان القيمة الأفتراضية للخصائص المرفقة Grid.Row و Grid.Column هي صفر(بمعنى الأول).

post-173477-1250886558_thumb.png

حجم الأعمدة والصفوف:

تقدم Grid ثلاث طرق لتحديد ارتفاع الصف وعرض الأعمدة:

- الحجم المطلق (Absolute size): حيث يتم تعيين رقم يمثل عدد الوحدات التي يشغلها العرض او الأرتفاع

<ColumnDefinition Width="100"/>

- الحجم التلقائي(Automatic size): حيث يعطى الصف او العمود القدر الذي يحتاج اليه تماما (استنادا على حجم المحتوى)

 <ColumnDefinition Width="Auto"/>

- الحجم النسبي(Proportional size): حيث يتم تقسيم المساحة المعطاة على الصفوف اوالأعمدة

 <ColumnDefinition Width="*"/>

وبشكل افتراضي، يكون التناسب متساويا ما لم نقم بإضافة رقم معين يسبق النجمة مثل:

<RowDefinition Height="*"/>
<RowDefinition Height="2*"/>

بهذا تكون نسبة الصف الأول إلى الصف الثاني هي 1 إلى 2.

عمل مربع الحوار السابق باستخدام Grid:

باستخدام هذه الطرق في التحجيم فإنه يمكننا استخدام Grid من اجل إنشاء نفس مربع الحوار السابق على النحو التالي :

<Grid ShowGridLines="True">
		<Grid.RowDefinitions>
			<RowDefinition Height="*"></RowDefinition>
			<RowDefinition Height="Auto"></RowDefinition>
		</Grid.RowDefinitions>
		<TextBox Margin="10" Grid.Row="0">This is a test.</TextBox>
		<StackPanel Grid.Row="1" HorizontalAlignment="Right" Orientation="Horizontal">
			<Button Margin="10,10,2,10" Padding="3">OK</Button>
			<Button Margin="2,10,10,10" Padding="3">Cancel</Button>
		</StackPanel>
	</Grid>

الخاصية ShowGridLines:

يمكن عرض خطوط الشبكة في Grid بتعيين هذه الخاصية إلى True (كما يظهر في المثال السابق).

الخصائص المرفقة Grid.RowSpan و Grid.ColumnSpan

يمكننا ان نجعل العنصر يشغل اكثر من صف واحد او عمود واحد من خلال الخصائص Grid.RowSpan و Grid.ColumnSpan، فعلى سبيل المثال لو اردنا ان يكون الزر في الصف الأول والعمود الأول ويشغل صفين وعمودين فإننا نكتب :

<Button Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Grid.ColumnSpan="2">Span Button</Button>

تقسيم النوافذ باستخدام GridSplitter

باستخدام GridSplitter يمكننا ان نجعل المستخدم قادرا على تغيير عرض العمود او ارتفاع الصف بنفس الطريقة التي تظهر في نوافذ مثل Windows Explorer حيث يكون بالأمكان تغيير عرض قائمة المجلدات عن طريق سحب حافتها في الأتجاه المطلوب.

post-173477-1250886672_thumb.png

إضافة GridSplitter إلى Grid عملية سهلة رغم ان الطريقة غريبة بعض الشئ،

ومن الجيد ان نتذكر التالي:

- يجب وضع GridSplitter داخل خلية في Grid ، هذه الخلية يمكن ان تحتوي على عناصر اخرى وفي هذه الحالة يجب ان نتأكد من هذه العناصر لا تقوم بإخفاء GridSplitter (بمعنى تغطيه) عن طريق تعيين الهوامش (Margin). والأفضل ان نقوم بعمل عمود او صف مخصص لـ GridSplitter

- لا يقوم GridSplitter بتعديل حجم الخلية فقط انما يقوم بتعديل حجم الصف او العمود بالكامل، ولكي نجعل هذا السلوك ينسجم مع المظهر في UI فإن علينا ان نجعل GridSplitter يمتد على طول الصف او العمود المطلوب باستخدام الخصائص Grid.RowSpan و Grid.ColumnSpan.

- مبدأيا يكون GridSplitter غير مرئيا ، ومن اجل ان نجعله مرئيا فلا بد من اعطائه حجم معين ينسجم مع الأتجاه الذي يعمل عليه. عن طريق اعطائه عرض معين (مع الأعمدة) او طول معين (مع الصفوف).

- تحدد محاذاة GridSplitter طريقة عمله ، بمعنى هل سيعمل كمقسم افقي (لتغيير حجم الصفوف) او كمقسم رأسي (لتغيير حجم الأعمدة) ، فمن اجل ان يعمل كمقسم افقي فإنه يجب تعيين الخاصية VerticalAlignment إلى Center بحيث يتم تغيير حجم الصف في الأعلى والصف في الأسفل. ومن اجل ان يعمل كمقسم رأسي فإنه يجب تعيين الخاصية HorizontalAlignment إلى Center بحيث يتم تغيير حجم العمود في اليسار والعمود في اليمين. (يمكن ايضاً استخدام الخصائص ResizeDirection و ResizeBehavior في GridSplitter من اجل تحديد السلوك المطلوب)

المثال التالي يوضح كيفية عمل مقسم رأسي لتغيير حجم الأعمدة :

<Grid>
		<Grid.RowDefinitions>
			<RowDefinition></RowDefinition>
			<RowDefinition></RowDefinition>
		</Grid.RowDefinitions>
		<Grid.ColumnDefinitions>
			<ColumnDefinition MinWidth="100"></ColumnDefinition>
			<ColumnDefinition Width="Auto"></ColumnDefinition>
			<ColumnDefinition MinWidth="50"></ColumnDefinition>
		</Grid.ColumnDefinitions>
		<Button Grid.Row="0" Grid.Column="0" Margin="3">Left</Button>
		<Button Grid.Row="0" Grid.Column="2" Margin="3">Right</Button>
		<Button Grid.Row="1" Grid.Column="0" Margin="3">Left</Button>
		<Button Grid.Row="1" Grid.Column="2" Margin="3">Right</Button>
		<GridSplitter Grid.Row="0" Grid.Column="1" Grid.RowSpan="2"
			Width="3" VerticalAlignment="Stretch" HorizontalAlignment="Center"
			ShowsPreview="False"></GridSplitter>
</Grid>

post-173477-1250886672_thumb.png

الخاصية ShowsPreview :

تكون قيمة الخاصية ShowsPreview في GridSplitter هي False بشكل افتراضي ، مايعني ان GridSplitter سوف يقوم بتغيير حجم العمود او الصف مباشرة خلال عملية السحب، وعند تغيير هذه الخاصية إلى True فإن GridSplitter سوف يسمح للمستخدم ان يقوم بمعاينة الحجم المحدد اولا وعند تحرير زر الماوس فإن الحجم الجديد يتم تطبيقه.

تم تعديل هذه المشاركة بواسطة HassanAlattas في 21 أغسطس 2009 في 23:51

[وسط]لا اله الا انت سبحانك انى كنت من الظالمين

[/وسط]

#3

أخي العزيز شكرا على مجهوداتك وكل عام وانت بخير

ولكن عندي استفسار هل يجب ان اتعلم لغة Xaml لكي أبرمج بالWPF ولا يكفي أني اكون عارف C# او فيجوال بيسك ؟

فلسطين .. سوريا ..بورما ......وماذا بعد ؟!

سابقا

medo_programming

موقعي : www.alkhayat-it.com

مواضيع مهمه

-----------------------------------------------:

تعلم كل شىء عن الTriggers

#4

وكل عام وانت بخير اخي العزيز,,

بالنسبة لسؤالك,,

نعم يجب ان تتعلم XAML، على الرغم من ان الشئ الذي نقوم بعمله XAML يمكننا ايضاً القيام به من خلال كود C# او VB ، لكن المشكلة في حجم الكود الذي سوف تحتاج إلى كتابتة ، فما نستطيع ان نقوم به في بضعة اسطر في XAML قد يقابله الكثير من الأسطر في الكود المكافئ بـ C# او VB (ويحتاج إلى مزيد من الخبرة).

والفكرة في WPF ان نقوم بتعريف واجهة المستخدم من خلال XAML ، بينما نقوم بتعريف السلوك او المنطق المطلوب لتلك الواجهة من خلال الكود (Code-Behind) .

[وسط]لا اله الا انت سبحانك انى كنت من الظالمين

[/وسط]

#5

مشكور أخي على التوضيح

فلسطين .. سوريا ..بورما ......وماذا بعد ؟!

سابقا

medo_programming

موقعي : www.alkhayat-it.com

مواضيع مهمه

-----------------------------------------------:

تعلم كل شىء عن الTriggers

#6

الصراحة موضوع رائع

بارك الله بيك اخي

و الله اشتاقينا للمواضيع الي مثل هذا الموضوع اتمنى ان تكمل المشوار

الWPF من التقنيات المهمة حاليا و اغلب المبيرمجين العرب لا يعرف مدى اهميتها

و اي مساعدة انا حاضر (الي مثلك ما يحتاج مساعدة) :wink:

#7

جزاك الله خيرا اخي الكريم

بالتأكيد احتاج إلى المساعدة،,

WPF موضوع كبير جدا ، وانا على يقين بان في المنتدى من لديه الخبرة والمعرفة في التعامل مع WPF ، وانتظر مشاركاتهم بفارغ الصبر .

تحياتي,,

[وسط]لا اله الا انت سبحانك انى كنت من الظالمين

[/وسط]

مواضيع مشابهة