سؤال

عند استخدام الموارد مثل الفرش والقوالب والأنماط في WPF، يمكن تحديدها إما على أنها StaticResources

<Rectangle Fill="{StaticResource MyBrush}" />

أو كمورد ديناميكي

<ItemsControl ItemTemplate="{DynamicResource MyItemTemplate}"  />

في معظم الأوقات (دائمًا؟)، يعمل أحدهما فقط والآخر سيطرح استثناءً أثناء وقت التشغيل.لكن أود أن أعرف السبب:

  • ما هو الفرق الرئيسي.مثل الذاكرة أو الآثار المترتبة على الأداء
  • هل توجد قواعد في WPF مثل "الفرش ثابتة دائمًا" و"القوالب ديناميكية دائمًا" وما إلى ذلك؟

أنا يفترض الاختيار بين Static و Dynamic ليس تعسفيًا كما يبدو ...لكني لا أستطيع رؤية النمط.

هل كانت مفيدة؟

المحلول

أ StaticResource سيتم حلها وتعيينها إلى الخاصية أثناء تحميل XAML الذي يحدث قبل تشغيل التطبيق فعليًا.سيتم تعيينه مرة واحدة فقط وسيتم تجاهل أي تغييرات في قاموس الموارد.

أ DynamicResource يقوم بتعيين كائن تعبير للخاصية أثناء التحميل ولكنه لا يبحث فعليًا عن المورد حتى وقت التشغيل عندما يُطلب من كائن التعبير القيمة.يؤدي هذا إلى تأجيل البحث عن المورد حتى يتم الحاجة إليه في وقت التشغيل.من الأمثلة الجيدة على ذلك الإشارة إلى مورد تم تحديده لاحقًا في XAML.مثال آخر هو المورد الذي لن يكون موجودًا حتى وقت التشغيل.سيتم تحديث الهدف إذا تم تغيير قاموس المورد المصدر.

نصائح أخرى

لقد كنت في حيرة من أمرهم أيضًا.انظر هذا المثال أدناه:

<Window x:Class="WpfApplicationWPF.CommandsWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="CommandsWindow" Height="300" Width="300">

    <StackPanel>
        <Button Name="ButtonNew" 
                Click="ButtonNew_Click" 
                Background="{DynamicResource PinkBrush}">NEW</Button>
        <Image Name="ImageNew" 
               Source="pack://application:,,,/images/winter.jpg"></Image>
    </StackPanel>


    <Window.Background>
        <DynamicResource ResourceKey="PinkBrush"></DynamicResource>
    </Window.Background>

</Window>

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

إذا أضفت الكود أدناه للنقر على حدث Button، نظرًا لأنهم يستخدمون DynamicResource، فسيتم تحديث الخلفية وفقًا لذلك.

private void ButtonNew_Click(object sender, RoutedEventArgs e)
{
    this.Resources.Add(  "PinkBrush"
                         ,new SolidColorBrush(SystemColors.DesktopColor)
                       );
}

إذا كانوا قد استخدموا StaticResource:

  • يجب الإعلان عن المورد في XAML
  • وذلك أيضًا "قبل" استخدامها.

آمل أن أكون قد أزلت بعض الالتباس.

سيتم حل StaticResource عند إنشاء الكائن.
سيتم تقييم DynamicResource وحلها في كل مرة يحتاج فيها التحكم إلى المورد.

تسمح لك الموارد المنطقية بتعريف الكائنات في XAML، والتي لا تعد جزءًا من الشجرة المرئية ولكن يمكن استخدامها في واجهة المستخدم الخاصة بك.أحد أمثلة الموارد المنطقية هو الفرشاة، والتي تُستخدم لتوفير نظام الألوان.بشكل عام، يتم تعريف هذه الكائنات على أنها موارد يتم استخدامها بواسطة عناصر متعددة من التطبيقات.

<Window.Resources>
    <RadialGradientBrush x:Key="myGradientBrush">
        <GradientStop Color="Green" Offset="0"/>
        <GradientStop Color="Blue" Offset="2"/>
    </RadialGradientBrush>
</Window.Resources>

الآن، يمكن استخدام المورد المعلن أعلاه كمورد ثابت أو ديناميكي.إحدى النقاط التي يجب تذكرها هي أنه عند استخدام الموارد الثابتة، يجب تعريفها أولاً في كود XAML، قبل أن تتم الإشارة إليها.يمكن استخدام الموارد الثابتة والديناميكية على النحو التالي:

<Grid Background="{StaticResource myGradientBrush}"></Grid>

أو:

<Grid Background="{DynamicResource myGradientBrush}"></Grid>

يكمن الاختلاف بين StaticResource وDynamicResource في كيفية استرداد الموارد بواسطة العناصر المرجعية.يتم استرداد StaticResource مرة واحدة فقط بواسطة العنصر المرجعي ويتم استخدامه طوال عمر المورد.من ناحية أخرى، يتم الحصول على DynamicResource في كل مرة يتم فيها استخدام الكائن المشار إليه.

وبعبارة أبسط، إذا تم تغيير خاصية اللون الخاصة بـ RadialGradientBrush في الكود إلى البرتقالي والوردي، فسوف تنعكس على العناصر فقط عند استخدام المورد كـ DynamicResource.يوجد أدناه رمز لتغيير المورد في الكود:

RadialGradientBrush radialGradientBrush =
    new RadialGradientBrush(Colors.Orange, Colors.Pink);
this.Resources["myGradientBrush"] = radialGradientBrush;

عيب DynamicResource هو أنه يقلل من أداء التطبيق لأنه يتم استرداد الموارد في كل مرة يتم استخدامها.أفضل الممارسات هي استخدام StaticResource حتى يكون هناك سبب محدد لاستخدام DynamicResource.

مصدر:
وبف:الموارد الثابتة مقابل.DynamicResource

  1. يستخدم StaticResource أولاً قيمة.يستخدم DynamicResource آخر قيمة.
  2. يمكن استخدام DynamicResource للتصميم المتداخل، ولا يمكن استخدام StaticResource.

لنفترض أن لديك قاموس النمط المتداخل هذا.يوجد LightGreen على مستوى الجذر بينما يكون اللون الوردي متداخلاً داخل الشبكة.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style TargetType="{x:Type Grid}">
        <Style.Resources>
            <Style TargetType="{x:Type Button}" x:Key="ConflictButton">
                <Setter Property="Background" Value="Pink"/>
            </Style>
        </Style.Resources>
    </Style>
    <Style TargetType="{x:Type Button}" x:Key="ConflictButton">
        <Setter Property="Background" Value="LightGreen"/>
    </Style>
</ResourceDictionary>

في رؤيه:

<Window x:Class="WpfStyleDemo.ConflictingStyleWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ConflictingStyleWindow" Height="100" Width="100">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Styles/ConflictingStyle.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>
        <Button Style="{DynamicResource ConflictButton}" Content="Test"/>
    </Grid>
</Window>

سوف يعرض StaticResource الزر كـ LightGreen، وهي القيمة الأولى التي وجدها في النمط.سيتجاوز DynamicResource زر LightGreen باللون الوردي لأنه يعرض الشبكة.

StaticResourceStaticResource

DynamicResourceDynamicResource

ضع في اعتبارك أن VS Designer يتعامل مع DynamicResource على أنه StaticResource.سوف تحصل على القيمة الأولى.في هذه الحالة، سيعرض VS Designer الزر باللون LightGreen على الرغم من أنه سينتهي باللون الوردي.

سوف يقوم StaticResource بإلقاء خطأ عند إزالة نمط مستوى الجذر (LightGreen).

ما هو الفرق الرئيسي.مثل الذاكرة أو الآثار المترتبة على الأداء

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

يتم استرداد الموارد الثابتة مرة واحدة عن طريق العنصر المرجعي ويتم استخدامها طوال عمر الموارد.حيث أن DynamicResources تسترد كل مرة يتم استخدامها.

الجانب السلبي للموارد الديناميكية هو أنها تميل إلى تقليل أداء التطبيق.

هل توجد قواعد في WPF مثل "الفرش ثابتة دائمًا" و"القوالب ديناميكية دائمًا" وما إلى ذلك؟

أفضل الممارسات هي استخدام الموارد الثابتة ما لم يكن هناك سبب محدد مثل رغبتك في تغيير المورد في الكود الموجود خلفك ديناميكيًا.مثال آخر على المثيل الذي تريد فيه استخدام الموارد الديناميكية يتضمن عند استخدام SystemBrushes وSystenFonts وSystem Parameters.

وجدت جميع الإجابات مفيدة، وأردت فقط إضافة حالة استخدام أخرى.

في سيناريو WPF المركب، يمكن لعنصر تحكم المستخدم الخاص بك الاستفادة من الموارد المحددة في أي نافذة/عنصر تحكم أصل آخر (الذي سيستضيف عنصر تحكم المستخدم هذا) من خلال الإشارة إلى هذا المورد باسم DynamicResource.

كما ذكر آخرون، سيتم البحث عن Staticresource في وقت الترجمة.لا يمكن أن تشير عناصر تحكم المستخدم إلى تلك الموارد التي تم تحديدها في الاستضافة/التحكم الأصلي.بالرغم من ذلك، يمكن استخدام DynamicResource في هذه الحالة.

فائدة هامة للموارد الديناميكية

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

ومع ذلك ، لن ترى أي فائدة ما لم يكن موردك كبيرًا ومعقدًا للغاية.

لا يمكن استخدام الموارد الديناميكية إلا عندما تكون الخاصية التي يتم تعيينها على كائن مشتق من كائن التبعية أو قابلة للتجميد حيث يمكن استخدام الموارد الثابتة في أي مكان.يمكنك تجريد التحكم بالكامل باستخدام الموارد الثابتة.

يتم استخدام الموارد الثابتة في الظروف التالية:

  1. عندما لا يكون تغيير مورد التفاعل في وقت التشغيل مطلوبًا.
  2. إذا كنت بحاجة إلى أداء جيد مع الكثير من الموارد.
  3. أثناء الرجوع إلى الموارد داخل نفس القاموس.

الموارد الديناميكية:

  1. قيمة الخاصية أو سمة محدد النمط غير معروفة حتى وقت التشغيل
    • يتضمن ذلك النظام والتطبيق والإعدادات القائمة على السمة
    • يتضمن هذا أيضًا مراجع للأمام.
  2. الرجوع إلى الموارد الكبيرة التي قد لا يتم تحميلها عند تحميل الصفحة أو النوافذ أو عنصر تحكم المستخدم.
  3. الرجوع إلى أنماط السمة في عنصر تحكم مخصص.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top