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

كيف يمكننا تطبيق مظهر مخصص لنافذة برنامج Wpf في زمن التشغيل

بدأه محمد سامر أبو سلو في 7 مارس 2008 · 0 رد · 721 مشاهدة · في Microsoft Visual Basic.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1

أنشئ تطبيق WPF جديد

سنقوم بالبداية بإنشاء عمودين داخل الشبكة الخاصة بالنافذة بحيث يكون الثاني بضعف حجم الأول وذلك بإدخال الكود التالي بعد <Grid> مباشرة وذلك في محرر XAML الخاص بنافذة المشروع

		<Grid.ColumnDefinitions>
			<ColumnDefinition Width="*"/>
			<ColumnDefinition Width="2*"/>
		</Grid.ColumnDefinitions>

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

		<Grid.RowDefinitions>
			<RowDefinition/>
			<RowDefinition/>
		</Grid.RowDefinitions>

سنضيف الآن بعض التحكمات للنموذج وسنبدأ بإضافة تحكم Label بحيث تكون محتوياته Street Address و التجانب الأفقي لليمين والشاقولي للوسط كما سنضيف صندوق نصوص يحتوي النص Enter Street Address وسيكون التجانب الأفقي لليسار والشاقولي للوسط وذلك بإدخال الكود التالي مباشرة بعد الكود السابق

<Label Content="Street Address" HorizontalAlignment="Right" VerticalAlignment="Center"></Label>
<TextBox Text="Enter a street address" HorizontalAlignment="Left" VerticalAlignment="Center"></TextBox>

سنحدد الآن اسما لصندوق النصوص وليكن txtAddress وذلك بتحديد قيمة الخاصية x:Name إلى القيمة المطلوبة كما سنحدد مكانه في الشبكة أيضا بتحديد قيمة الخاصيتين Grid.Column و Grid.Row فيصبح الكود الخاص بصندوق النصوص على الشكل التالي بعد التعديل

<TextBox Grid.Column="1" Grid.Row="0" x:Name="txtAddress" Text="Enter a street address" 
		 HorizontalAlignment="Left" VerticalAlignment="Center"></TextBox>

كما سنقوم بتحديد مكان الـ Label في الشبكة باستخدام Grid.Column و Grid.row وذلك بنفس الطريقة السابقة إضافة إلى أننا سنقوم بربط الـ Lable بصندوق النصوص باستخدام الخاصية Target لـ Label فيصبح الكود الخاص بـ Label على الشكل التالي

<Label Grid.Column="0" Grid.Row="0" Target="{Binding ElementName=txtAddress, Mode=OneWay}" 
	Content="Street Address" HorizontalAlignment="Right" VerticalAlignment="Center"></Label>

الآن سنقوم بإضافة زر أوامر باستخدام الكود التالي

<Button Grid.Column="1" Grid.Row="1" Content="Save Street Address" 
		HorizontalAlignment="Left" VerticalAlignment="Top" />

أضف المحرف _ في بداية نص Contenet الخاص بـ Label لتصبح قيمة تلك الخاصية

Content="_Street Address"

وذلك حتى يمكننا استخدام الخاصية Target للانتقال مباشرة لصندوق النصوص باستخدام الاختصار Alt-S بما أننا وضعنا المحرف _ قبل الحرف S

شغل البرنامج واختبره ويكون قد أصبح كود xaml الخاص بالنافذة كما يلي

<Window x:Class="Window1"
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	Title="Test WPF Skinning" Height="300" Width="300">
	<Grid>
		<Grid.ColumnDefinitions>
			<ColumnDefinition Width="*"/>
			<ColumnDefinition Width="2*"/>
		</Grid.ColumnDefinitions>
		<Grid.RowDefinitions>
			<RowDefinition/>
			<RowDefinition/>
		</Grid.RowDefinitions>
		<Label Grid.Column="0" Grid.Row="0" Target="{Binding ElementName=txtAddress, Mode=OneWay}" 
			   Content="_Street Address" HorizontalAlignment="Right" VerticalAlignment="Center"></Label>
		<TextBox Grid.Column="1" Grid.Row="0" x:Name="txtAddress" Text="Enter a street address" 
				 HorizontalAlignment="Left" VerticalAlignment="Center"></TextBox>
		<Button Grid.Column="1" Grid.Row="1" Content="Save Street Address" 
				HorizontalAlignment="Left" VerticalAlignment="Top" />
	</Grid>
</Window>

انتقل إلى Solution Explorer وقم بفتح الملف Application.xaml كي نقوم بتحديد المظهر الخاص بأدواتنا هنا وسنبدأ بتحديد المظهر الخاص بـ Label وذلك بإدراج قسم Style التالي بعد <Application.Resources> مباشرة حيث سنقوم بتحديد قيمة اللون الأمامي وحجم الخط

<Style TargetType="{x:Type Label}" x:Key="LabelStyle">
	<Setter Property="Foreground" Value="Blue"></Setter>
	<Setter Property="FontSize" Value="12px"></Setter>
</Style>

وسنقوم الآن بتحديد مظهرين فارغين لكلا صندوق النصوص وزر الأوامر بحيث لن يغيرا شيئا في الوقت الحالي على مظهر التحكمين وذلك بإدخال الكود التالي مباشرة بعد الكود السابق

<Style TargetType="{x:Type TextBox}" x:Key="TextBoxStyle"></Style>
<Style TargetType="{x:Type Button}" x:Key="ButtonStyle"></Style>

وبهذا يصبح الكود الخاص بـ Application.xaml حتى الآن كالتالي

<Application x:Class="Application"
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	StartupUri="Window1.xaml">
	<Application.Resources>
		<Style TargetType="{x:Type Label}" x:Key="LabelStyle">
			<Setter Property="Foreground" Value="Blue"></Setter>
			<Setter Property="FontSize" Value="12px"></Setter>
		</Style>
		<Style TargetType="{x:Type TextBox}" x:Key="TextBoxStyle"></Style>
		<Style TargetType="{x:Type Button}" x:Key="ButtonStyle"></Style>
	</Application.Resources>
</Application>

ولربط هذه المظاهر الجديدة مع التحكمات نعود لكود xaml الخاص بالنافذة ونضيف الخاصية Style لكل من الـ Label و صندوق النصوص و زر الأوامر فيصبح الكود الخاص بالتحكمات الثلاثة على الشكل

<Label Grid.Column="0" Grid.Row="0" Target="{Binding ElementName=txtAddress, Mode=OneWay}" 
	   Content="_Street Address" HorizontalAlignment="Right" VerticalAlignment="Center"
			   Style="{DynamicResource LabelStyle}"></Label>
<TextBox Grid.Column="1" Grid.Row="0" x:Name="txtAddress" Text="Enter a street address" 
		 HorizontalAlignment="Left" VerticalAlignment="Center" 
		 Style="{DynamicResource TextBoxStyle}"></TextBox>
<Button Grid.Column="1" Grid.Row="1" Content="Save Street Address" 
		HorizontalAlignment="Left" VerticalAlignment="Top" Style="{DynamicResource ButtonStyle}"/>

ونلاحظ هنا أننا استخدمنا DynamicResource في الخاصية Style لربط مع الشكل المراد حيث نحدد أن هذه الخاصية يمكن أن يتم تغييرها في زمن التشغيل ديناميكيا وأن المظهر المطلوب قد يكون موجودا وقد لا يكون موجودا بينما لو استخدمنا StaticResource في هذه النقطة سنخبر البرنامج أننا نتوقع وجود ذلك المظهر وأنه لن يتم تغييره

شغل البرنامج واختبره

أضف الخاصية Click لتعريف الزر وذلك لإضافة إجراء لمعالجة حدث النقر على الزر بحيث تكون على الشكل

Click="Button_Click"

ويصبح تعريف الزر في النهاية على الشكل

<Button Grid.Column="1" Grid.Row="1" Content="Save Street Address" Click="Button_Click"
		HorizontalAlignment="Left" VerticalAlignment="Top" Style="{DynamicResource ButtonStyle}"/>

ثم انتقل لمحرر الكود الخاص بالملف Window1.xaml.vb وأضف إجراء معالجة حدث النقر على الزر وأضف استيرادا لـ System.IO و لـ System.Windows.Markup في بداية الملف وأنشئ إجراءا فارغا لحدث النقر على الزر كما يظهر في الكود التالي

Imports System.IO
Imports System.Windows.Markup

Class Window1
	Sub Button_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)

	End Sub
End Class

اختر Add New Item من القائمة Project ثم أضف ملفا من النوع WPF Resource Dictionary للمشروع وقم بتسميته CrazyStyle.xaml وقم بتعديل الخاصية Copy to output directory الخاصة به إلى Copy if newer وأيضا قيمة الخاصية Build Action إلى Content حيث سنستخدمه كملف Skin للنافذة بحيث أننا سنستخدم الخاصية Dynamic Resources في WPF لتعمل كما لو أننا نستخدم Skin للمشروع وقم بتعديل محتويات كود xaml الخاص به ليصبح كما في الكود التالي حيث سيحتوي على الأشكال الخاصة بتحكمات نافذة المشروع وبنفس الطريقة التي استخدمناها منذ قليل

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

	<Style TargetType="{x:Type Label}" x:Key="LabelStyle">
		<Setter Property="Foreground" Value="Red" />
		<Setter Property="FontSize" Value="16px" />
	</Style>
	<Style TargetType="{x:Type TextBox}" x:Key="TextBoxStyle">
		<Setter Property="Background">
			<Setter.Value>
				<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
					<GradientStop Offset=".1" Color="AliceBlue" />
					<GradientStop Offset=".5" Color="AntiqueWhite" />
					<GradientStop Offset="1" Color="Aquamarine" />
				</LinearGradientBrush>
			</Setter.Value>
		</Setter>
	</Style>
	<Style TargetType="{x:Type Button}" x:Key="ButtonStyle">
		<Setter Property="Foreground" Value="Blue" />
		<Setter Property="FontSize" Value="16px" />
	</Style>

</ResourceDictionary>

الآن عد إلى إجراء معالجة الحدث Click للزر الذي أنشأناه سابقا وقم بتعديله ليصبح كما في الكود التالي الذي يقوم بتعريف المتغير rd ليكون من النوع ResourceDictionary ثم يستخدم FileStream لفتح الملف CrazyStyle.xaml للقراءة ثم نستخدم XamlReader.Load لقراءة محتويات الملف مستخدمين الدالة CType لتحويل نوع الناتج المقروء إلى ResourceDictionary ثم نقوم بوضع تلك القيمة في المتغير Rd الذي سنضبطه ليكون المصدر الحالي Current Resource للتطبيق وذلك بإسناد قيمته إلى Application.Current.Resources

Sub Button_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
	Dim rd As ResourceDictionary = Nothing
	Using fs As New FileStream("CrazyStyle.xaml", FileMode.Open, FileAccess.Read)
		rd = CType(XamlReader.Load(fs), ResourceDictionary)
	End Using
	Application.Current.Resources = rd
End Sub

شغل التطبيق واختبره

يرجى عدم طلب إرفاق مثال مع الموضوع لأن الشرح واضح أولا وثانيا أريد أن أرى مثالا يعمل بشكل صحيح مرفق من قبل أحد الإخوة الذين قرأوا الموضوع

تم تعديل هذه المشاركة بواسطة محمد سامر أبو سلو في 7 مارس 2008 في 23:26

عن عائشة رضي الله عنها أن النبي صلى الله عليه وسلم قال: إن الله يحب إذا عمل أحدكم عملا أن يتقنه

نعيب زماننا والعيب فينا ... وما لزماننا عيب سوانا

ونهجو ذا الزمان بغير ذنب ... ولو نطق الزمان لنا هجانا

محمد سامر أبو سلو

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

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…