سئوالات و مباحث WPF

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بعد استاد ، گاها انگار کنترل DoubleUpDown ام کند میشه .
مثلا وقتی روش کلیک میکنم تا عدد وارد کنم ، من عدد را مینویسم اما همون لحظه چیزی نمینویسه و cpu چند ثانیه اندکی درگیری اش بالاتر میره (مثلا 20 درصد که درگیر بود ، به 40 درصد میرسه و بعد از 4 ثانیه ی دیگه درگیریش که پایین اومد به روال قبل ، تازه توی کنترل DoubleUpDown ، اون عدد را مینویسه .

این ، گاها پیش میاد و مثلا اون صفحه (که در تنظیمات هست) را میبندم (کل برنامه را نمیبندم) و بعد دوباره وارد صفحه (ی تنظیمات) اش میشم ، معمولا دفعه ی بعد ، خوب میشه .
البته گاها پیش میاد و نه همیشه .
این بخاطر چی میتونه باشه؟ بخاطر نوشتن تمپلیت و استایل برای این کنترل که نیست؟ هست؟ وگرنه همیشه باید این طور میشد .
تشکر استاد .
 

the_king

مدیرکل انجمن
خیلی ممنون استاد
باشه ، key نمینویسم (اما فرقی هم نمیکنه توی ارور دادن یا ندادن یا درست اجرا شدن یا نشدن) .
بله ، نوشته شده که در زیر ، پیوست میکنم (شامل چندین نوع از کنترل های دیگه هم میشه که به کنترل ShapeTextButton ربطی نداره) (همون چیزی هه که قبلا در جریانید) .
اون Grid ئه ریشه که در پست 558 دادم ، خودش فرزند Window ای هست که Style ئه اون Window ، بصورت پیش فرض از استایل DarkStyle استفاده میکنه (که در فایل StyleResource.xaml هست که در فایل پیوست زیر موجود هست ، تعریف شد که در جریانید) .
به مثالی که میزنم توجه کنید.
این کد رو اجرا کنید :
C#:
            var style = (Style)Application.Current.TryFindResource(typeof(Button));
            MessageBox.Show((style == null) ? "null" : "not null");
این کد رو هم اجرا کنید :
C#:
            var style = (Style)Application.Current.TryFindResource(typeof(MyButton));
            MessageBox.Show((style == null) ? "null" : "not null");

    public class MyButton : Button
    {
    }
تفاوت در چیه؟ در اینکه MyButton برای خودش هیچ Style پیشفرضی نداره.
حالا اگر بخواهیم با این وضعیت همچین کدی رو بنویسیم خطا میده که اون Style پیشفرض برای MyButton وجود نداره که BaseOn باشه :
XML:
<Window.Resources>
<Style TargetType="local:MyButton" BasedOn="{StaticResource {x:Type local:MyButton}}"/>
</Window.Resources>
حالا اگر در ResourceDictionary جدیدی اون Style پیشفرض رو توصیف کنم همینطوری بدون اشاره به ResourceDictionary مشکل بر طرف میشه؟ خیر.
XML:
<ResourceDictionary>
    <Style x:Key="{x:Type local:MyButton}" TargetType="local:MyButton"/>
</ResourceDictionary>
ولی اگر اون ResourceDictionary رو اضافه کنم حداقل اون BasedOn خطا نمیده :
XML:
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Dictionary1.xaml"/>
            </ResourceDictionary.MergedDictionaries>
            <Style TargetType="local:MyButton" BasedOn="{StaticResource {x:Type local:MyButton}}"/>
        </ResourceDictionary>
    </Window.Resources>
ولی همچنان برای نوع MyButton هیچ Style پیشفرضی وجود نداره :
C#:
            var style = (Style)Application.Current.TryFindResource(typeof(MyButton));
            MessageBox.Show((style == null) ? "null" : "not null");

ولی اگر همچین چیزی هم بود دیگه نه null بود و نه خطا میداد، چون از همون ابتدا در Resources برنامه Style پیشفرض توصیف شده :
XML:
    <Application.Resources>
        <Style TargetType="local:MyButton"/>
    </Application.Resources>
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
به مثالی که میزنم توجه کنید.
این کد رو اجرا کنید :
C#:
            var style = (Style)Application.Current.TryFindResource(typeof(Button));
            MessageBox.Show((style == null) ? "null" : "not null");
این کد رو هم اجرا کنید :
C#:
            var style = (Style)Application.Current.TryFindResource(typeof(MyButton));
            MessageBox.Show((style == null) ? "null" : "not null");

    public class MyButton : Button
    {
    }
تفاوت در چیه؟ در اینکه MyButton برای خودش هیچ Style پیشفرضی نداره.
حالا اگر بخواهیم با این وضعیت همچین کدی رو بنویسیم خطا میده که اون Style پیشفرض برای MyButton وجود نداره که BaseOn باشه :
XML:
<Window.Resources>
<Style TargetType="local:MyButton" BasedOn="{StaticResource {x:Type local:MyButton}}"/>
</Window.Resources>
حالا اگر در ResourceDictionary جدیدی اون Style پیشفرض رو توصیف کنم همینطوری بدون اشاره به ResourceDictionary مشکل بر طرف میشه؟ خیر.
XML:
<ResourceDictionary>
    <Style x:Key="{x:Type local:MyButton}" TargetType="local:MyButton"/>
</ResourceDictionary>
ولی اگر اون ResourceDictionary رو اضافه کنم حداقل اون BasedOn خطا نمیده :
XML:
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Dictionary1.xaml"/>
            </ResourceDictionary.MergedDictionaries>
            <Style TargetType="local:MyButton" BasedOn="{StaticResource {x:Type local:MyButton}}"/>
        </ResourceDictionary>
    </Window.Resources>

ولی همچنان برای نوع MyButton هیچ Style پیشفرضی وجود نداره :
C#:
            var style = (Style)Application.Current.TryFindResource(typeof(MyButton));
            MessageBox.Show((style == null) ? "null" : "not null");

ولی اگر همچین چیزی هم بود دیگه نه null بود و نه خطا میداد، چون از همون ابتدا در Resources برنامه Style پیشفرض توصیف شده :
XML:
    <Application.Resources>
        <Style TargetType="local:MyButton"/>
    </Application.Resources>

خیلی ممنون استاد .
منظورتون اینه که قبل از اینکه هر کدی شروع بشه ، اول یه استایل پیش فرض (استایلی که هیچ مقداردهی یا در واقع Setter ای نداره . فقط TargetType و همچنین Key اش که هر دو ، مقدارِ {x:Type CustomControls:ShapeTextButton} در اینجا دارن) بهش بدیم . یعنی استایل پیش فرض اش این میشه :

XML:
<Style x:Key="{x:Type CustomControls:ShapeTextButton}" TargetType="{x:Type CustomControls:ShapeTextButton}"/>

و نکته ی مهم اش اینه که قبل از اینکه کد xaml ای را فراخونی کنیم ، درون Application.Resources ، این کد را اول فراخونی کنیم . درست میگم؟
اگه آره ، من کد بالا (استایل پیش فرض برای ShapeTextButton) را در فایل StyleResource.xaml ، در همون خط اول (قبل از خطی که DarkStyle تعریف بشه) ، نوشتم .

این باعث شد که در کدی که در پست 558 داده بودم ، دیگه اون ارور را نده اما اون استایل ای که در Grid.Resources ئه همون کد در پست 558 داده بودم ، اِعمال نمیشه (کلیدش را هم حذف کردم) . حتی استایل ای که درون DarkStyle برای ShapeTextButton تعریف کرده بودم هم اِعمال نمیشه .
اما وقتی اون Grid.Resources ای که در پست 558 داده بودم را حذف میکنم (استایل پیش فرض ShapeTextButton که درون فایل StyleResource.xaml ، قبل از DarkStyle تعریف کردم ، سر جاش هست) ، درست میشه و از استایل ای که در DarkStyle برای ShapeTextButton تعریف کرده بودم ، استفاده میکنه .

مشکل الان از کجاست؟


---------------------------------------------------------------------


استاد ، پست 561 را هم بی زحمت جواب میدین؟
واسه ی چی میتونه باشه؟

تشکر استاد :rose:
 

the_king

مدیرکل انجمن
خیلی ممنون استاد .
منظورتون اینه که قبل از اینکه هر کدی شروع بشه ، اول یه استایل پیش فرض (استایلی که هیچ مقداردهی یا در واقع Setter ای نداره . فقط TargetType و همچنین Key اش که هر دو ، مقدارِ {x:Type CustomControls:ShapeTextButton} در اینجا دارن) بهش بدیم . یعنی استایل پیش فرض اش این میشه :

XML:
<Style x:Key="{x:Type CustomControls:ShapeTextButton}" TargetType="{x:Type CustomControls:ShapeTextButton}"/>
نه. اولا شما چرا چیزی که نوشتنش سودی نداره می نویسید؟ اون x:Key ئه "{x:Type CustomControls:ShapeTextButton}" برای چیه؟
ثانیا قبل از هر کدی و Style خالی که قاعده و مبنا نیست. خطای پیدا نشدن StaticResource که واضح ئه، اگر در جایی خطای could not be resolved داد، باید به این فکر کنید که اون StaticResource باید پیش از رسیدن به اون کد باید توصیف میشده که نشده.
حالا اینکه توصیف قبل از هر کدی باشه یا Style خالی باشه یا خیلی مقدار داخلش باشه که دیگه در شرایط حل مشکل جایی نداره، اهمیتی نداره.

و نکته ی مهم اش اینه که قبل از اینکه کد xaml ای را فراخونی کنیم ، درون Application.Resources ، این کد را اول فراخونی کنیم . درست میگم؟
اگه آره ، من کد بالا (استایل پیش فرض برای ShapeTextButton) را در فایل StyleResource.xaml ، در همون خط اول (قبل از خطی که DarkStyle تعریف بشه) ، نوشتم .
داخل Application.Resources جای مناسبی است اما لازم نیست که حتما داخل اون باشه.

این باعث شد که در کدی که در پست 558 داده بودم ، دیگه اون ارور را نده اما اون استایل ای که در Grid.Resources ئه همون کد در پست 558 داده بودم ، اِعمال نمیشه (کلیدش را هم حذف کردم) . حتی استایل ای که درون DarkStyle برای ShapeTextButton تعریف کرده بودم هم اِعمال نمیشه.

اما وقتی اون Grid.Resources ای که در پست 558 داده بودم را حذف میکنم (استایل پیش فرض ShapeTextButton که درون فایل StyleResource.xaml ، قبل از DarkStyle تعریف کردم ، سر جاش هست) ، درست میشه و از استایل ای که در DarkStyle برای ShapeTextButton تعریف کرده بودم ، استفاده میکنه .

مشکل الان از کجاست؟
کد که پیش روی شما است، باید بتوانید مشکل رو پیدا کنید.
وراثت Style ها رو بررسی کنید. حتی لازم شد با مثال های کوچک و ساده تمرین کنید تا براتون ابهام پیش نیاد.
در کدتون بررسی کنید و ببینید چه چیزی باعث میشه که DarkStyle روی کنترل ای اعمال بشه.
ببینید اون DarkStyle وارث کدوم Style ئه، بعد ببینید آیا OverridesDefaultStyle داره یا نه و ...


استاد ، پست 561 را هم بی زحمت جواب میدین؟
واسه ی چی میتونه باشه؟
نمیدونم. برای اینجور کارها باید با اجنه ارتباط برقرار کنم تا سخت و نرم افزار سیستم رو بررسی کنند. نمیتونم هیچ نظری بدم.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
نه. اولا شما چرا چیزی که نوشتنش سودی نداره می نویسید؟ اون x:Key ئه "{x:Type CustomControls:ShapeTextButton}" برای چیه؟
ثانیا قبل از هر کدی و Style خالی که قاعده و مبنا نیست. خطای پیدا نشدن StaticResource که واضح ئه، اگر در جایی خطای could not be resolved داد، باید به این فکر کنید که اون StaticResource باید پیش از رسیدن به اون کد باید توصیف میشده که نشده.
حالا اینکه توصیف قبل از هر کدی باشه یا Style خالی باشه یا خیلی مقدار داخلش باشه که دیگه در شرایط حل مشکل جایی نداره، اهمیتی نداره.


داخل Application.Resources جای مناسبی است اما لازم نیست که حتما داخل اون باشه.


کد که پیش روی شما است، باید بتوانید مشکل رو پیدا کنید.
وراثت Style ها رو بررسی کنید. حتی لازم شد با مثال های کوچک و ساده تمرین کنید تا براتون ابهام پیش نیاد.
در کدتون بررسی کنید و ببینید چه چیزی باعث میشه که DarkStyle روی کنترل ای اعمال بشه.
ببینید اون DarkStyle وارث کدوم Style ئه، بعد ببینید آیا OverridesDefaultStyle داره یا نه و ...

خیلی ممنون استاد
استاد دو پروژه ای که پیوست میکنم (که خلاصه شده هست) را ببینید .
در پروژه ی DerivedStyle_1 که استایل را بصورت مستقیم ، بصورت زیر نوشتم :

XML:
<Style x:Key="{x:Type NameSpace:CustomButton}" TargetType="{x:Type NameSpace:CustomButton}">
        <Setter Property="Width" Value="100"/>
        <Setter Property="Height" Value="50"/>
    </Style>

هیچ مشکلی نیست و هر دو استایل (پدر و فرزند که اون فرزند ، در Resource ئه Grid تعریف شد) ، کاملا درست کار میکنه (استایل پیش فرض رو هم ننوشتم) .

اما در پروژه ی DerivedStyle_2 که استایل برای CustomButton را درون Resource ئه استایل دیگه (درون Resource ئه استایل DarkStyle) تعریف کردم :

XML:
    <Style x:Key="DarkStyle">
        <Style.Resources>
            <Style x:Key="{x:Type NameSpace:CustomButton}" TargetType="{x:Type NameSpace:CustomButton}">
                <Setter Property="Width" Value="100"/>
                <Setter Property="Height" Value="50"/>
            </Style>
        </Style.Resources>
    </Style>

و اون DarkStyle را در استایلِ Window فراخونی و استفاده کردم ، فقط در این صورت هست که در اون پروپرتی BasedOn ، مشکل و ارور Resolve که قبلا داده بود را میده .

من فکر میکنم مشکل از اینه که وقتی یک استایل را درون Resource ئه استایلِ دیگه تعریف میکنیم ، در این صورت ، وقتی BaseOn را تعریف میکنیم ، انگار نمیتونه اون استایل را پیدا کنه (اما نمیدونم چرا وقتی برای استایل Window ، اون DarkStyle را بکار میبریم (اگه استایل فرزند و تو در تو ننویسیم) ، مشکلی در پیدا کردن استایل نداره!


الان استاد یه روشی میتونین بگین که در حالی که از حالت دوم (یعنی استایلی را در Resource ئه استایلِ دیگه) استفاده میکنیم ، مشکل BaseOn هم حل بشه؟
یا اینکه پروژه ی دوم (DerivedStyle_2) (که هر دو پروژه ، خیلی ساده شده هست) را جوری تغییر میدین که مثل پروژه ی اول (که استایل تو در تو اش کار میکنه) ، قضیه ی استایل تو در توی پروژه ی دوم هم کار کنه؟



نمیدونم. برای اینجور کارها باید با اجنه ارتباط برقرار کنم تا سخت و نرم افزار سیستم رو بررسی کنند. نمیتونم هیچ نظری بدم.

مشکل (کدهای) کلاس DoubleUpDown میتونه باشه؟
یه چیزی شبیه باگ؟
یا مثلا ممکنه پروژه ای (پروژه ام) ، بد کمپایل بشه؟
و ...؟


------------------------------------------------------------------------------------

استاد ، برای ذخیره ی تنظیمات برنامه ، ذخیره در فایل xml را پیشنهاد میکنین یا ذخیره در فایل sqlite را یا کلا چیز دیگه ای؟
اگه میشه ، دلیل تون را هم بگید ، ممنون میشم؟
اگه پیشنهادتون xml هست ، اگه امنیت اش را بصورت نسبی خواستم تامین کنم ، از کتابخونه های رمزگذاری فایل در سی شارپ استفاده کنم؟


----------------------------------------------------------------------------------

استاد ، چرا درون متد Main در wpf ، انگار هر کدی خودمون بنویسیم ، اجرا نمیشه؟!
مثلا کد Debuge.WriteLine را نوشتم ، اجرا نشد . توی اینترنت دیدم کدهای Mutex را برای wpf توصیه کردن توی متد OnStartup بنویسیم اما برای winform را درون متد Main نوشتن .
چرا این طوره؟

تشکر استاد :rose:
 

پیوست ها

  • DerivedStyle_1.rar
    48.4 کیلوبایت · بازدیدها: 1
  • DerivedStyles_2.rar
    49.4 کیلوبایت · بازدیدها: 1

the_king

مدیرکل انجمن
خیلی ممنون استاد
استاد دو پروژه ای که پیوست میکنم (که خلاصه شده هست) را ببینید .
در پروژه ی DerivedStyle_1 که استایل را بصورت مستقیم ، بصورت زیر نوشتم :

XML:
<Style x:Key="{x:Type NameSpace:CustomButton}" TargetType="{x:Type NameSpace:CustomButton}">
        <Setter Property="Width" Value="100"/>
        <Setter Property="Height" Value="50"/>
    </Style>

هیچ مشکلی نیست و هر دو استایل (پدر و فرزند که اون فرزند ، در Resource ئه Grid تعریف شد) ، کاملا درست کار میکنه (استایل پیش فرض رو هم ننوشتم) .
یک لحظه صبر کنید. میگید Style پیشفرض رو ننوشتم. شما اول همچین کدی رو اجرا کنید تا ببینید Style پیشفرض داره یا نه :
C#:
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var style = (Style)Application.Current.TryFindResource(typeof(CustomButton));
            MessageBox.Show((style == null) ? "null" : "not null");
        }
داره، چون not null ئه. بعد بیایید اون دو تا Style رو که در پروژه اول دارید comment کنید (هر دو شون که خطایی هم رخ نده) که ببینید چطور Style پیشفرض غیب میشه و null میشه. حالا اون Style داخل StyleResource.xaml رو uncomment کنید تا Style پیشفرض برگرده. چرا میگید Style پیشفرض ننوشتم؟ پس اون Style داخل StyleResource.xaml چیه؟


اما در پروژه ی DerivedStyle_2 که استایل برای CustomButton را درون Resource ئه استایل دیگه (درون Resource ئه استایل DarkStyle) تعریف کردم :

XML:
    <Style x:Key="DarkStyle">
        <Style.Resources>
            <Style x:Key="{x:Type NameSpace:CustomButton}" TargetType="{x:Type NameSpace:CustomButton}">
                <Setter Property="Width" Value="100"/>
                <Setter Property="Height" Value="50"/>
            </Style>
        </Style.Resources>
    </Style>

و اون DarkStyle را در استایلِ Window فراخونی و استفاده کردم ، فقط در این صورت هست که در اون پروپرتی BasedOn ، مشکل و ارور Resolve که قبلا داده بود را میده .

من فکر میکنم مشکل از اینه که وقتی یک استایل را درون Resource ئه استایلِ دیگه تعریف میکنیم ، در این صورت ، وقتی BaseOn را تعریف میکنیم ، انگار نمیتونه اون استایل را پیدا کنه (اما نمیدونم چرا وقتی برای استایل Window ، اون DarkStyle را بکار میبریم (اگه استایل فرزند و تو در تو ننویسیم) ، مشکلی در پیدا کردن استایل نداره!
[/QUOTE]
شما وقتی یک Style رو به عنوان Style به المنتی معرفی می کنید (مثلا DarkStyle برای Window) اون صرفا Style اش میشه، معنی اش این نیست که Resource های Style ئه بشه جزو Resource های اون Window، منابع شون که ربطی بهم ندارند. اون Window فرزند اون Style نیست که به منابع Style ئه دسترسی داشته باشه. اینکه به DarkStyle دسترسی دارید صرفا به این خاطر ئه که منابع داخل StyleResource.xaml رو به Application.Resources اضافه کردید.

الان استاد یه روشی میتونین بگین که در حالی که از حالت دوم (یعنی استایلی را در Resource ئه استایلِ دیگه) استفاده میکنیم ، مشکل BaseOn هم حل بشه؟
به نظرتون خنده دار نیست؟ DarkStyle اگه نمیخواد Style پیشفرض CustomButton رو تعریف کنه چرا Style پیشفرضش رو داره؟
اگه قراره Style پیشفرضش رو تعریف کنه چرا اون یکی Style در Grid.Resources میخواد از نو ؟ بالاخره DarkStyle یا باید Style پیشفرض رو داشته باشه یا نداشته باشه. اگر همچین وظیفه ای به عهده DarkStyle نیست نباید Style پیشفرض باشه.

یا اینکه پروژه ی دوم (DerivedStyle_2) (که هر دو پروژه ، خیلی ساده شده هست) را جوری تغییر میدین که مثل پروژه ی اول (که استایل تو در تو اش کار میکنه) ، قضیه ی استایل تو در توی پروژه ی دوم هم کار کنه؟
DerivedStyles_3.rar

مشکل (کدهای) کلاس DoubleUpDown میتونه باشه؟
یه چیزی شبیه باگ؟
یا مثلا ممکنه پروژه ای (پروژه ام) ، بد کمپایل بشه؟
و ...؟
عرض کردم نمیدونم. بد کامپایل شدن اصلا معنی و مفهومی نداره.


استاد ، برای ذخیره ی تنظیمات برنامه ، ذخیره در فایل xml را پیشنهاد میکنین یا ذخیره در فایل sqlite را یا کلا چیز دیگه ای؟
اگه میشه ، دلیل تون را هم بگید ، ممنون میشم؟
اگه پیشنهادتون xml هست ، اگه امنیت اش را بصورت نسبی خواستم تامین کنم ، از کتابخونه های رمزگذاری فایل در سی شارپ استفاده کنم؟
پیشنهادی ندارم. اما به هر حال XML در جایی استفاده میشه که قراره داده در ساده ترین شکل ممکن و با ابتدایی ترین ویرایشگر ها قابل مشاهده و تغییر باشه، اگر نمیخواهید کسی اونها رو ببینه یا تغییر بده دیگه انتخاب XML منطقی نیست و مزیتی نداره.

استاد ، چرا درون متد Main در wpf ، انگار هر کدی خودمون بنویسیم ، اجرا نمیشه؟!
مثلا کد Debuge.WriteLine را نوشتم ، اجرا نشد . توی اینترنت دیدم کدهای Mutex را برای wpf توصیه کردن توی متد OnStartup بنویسیم اما برای winform را درون متد Main نوشتن .
چرا این طوره؟
حتما یک جای کار اشتباه کرده اید، گزینشی که نیست که بعضی ها رو اجرا کنه و بعضی ها رو نکنه.
 

پیوست ها

  • DerivedStyles_3.rar
    193.5 کیلوبایت · بازدیدها: 8

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
یک لحظه صبر کنید. میگید Style پیشفرض رو ننوشتم. شما اول همچین کدی رو اجرا کنید تا ببینید Style پیشفرض داره یا نه :
C#:
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var style = (Style)Application.Current.TryFindResource(typeof(CustomButton));
            MessageBox.Show((style == null) ? "null" : "not null");
        }
داره، چون not null ئه. بعد بیایید اون دو تا Style رو که در پروژه اول دارید comment کنید (هر دو شون که خطایی هم رخ نده) که ببینید چطور Style پیشفرض غیب میشه و null میشه. حالا اون Style داخل StyleResource.xaml رو uncomment کنید تا Style پیشفرض برگرده. چرا میگید Style پیشفرض ننوشتم؟ پس اون Style داخل StyleResource.xaml چیه؟

خیلی ممنون استاد از جواب کامل تون :rose:
بله . مفهومی که از استایل پیش فرض توی ذهنم شکل گرفته بود این بود که استایلی باشه که Setter نداشته باشه که اشتباه بود . متوجه شدم .
اگه اشتباه نکنم ، استایل پیش فرض ، به اولین استایل برای اون نوع داده ای که بنویسیم ، استایل پیش فرض محسوب میشه . درسته؟

شما وقتی یک Style رو به عنوان Style به المنتی معرفی می کنید (مثلا DarkStyle برای Window) اون صرفا Style اش میشه، معنی اش این نیست که Resource های Style ئه بشه جزو Resource های اون Window، منابع شون که ربطی بهم ندارند. اون Window فرزند اون Style نیست که به منابع Style ئه دسترسی داشته باشه.

فرق اینکه Resource ای در اون Window مشخص کنیم یا پروپرتیِ Style ئه اون ویندوز را (به DarkStyle و ...) مشخص و تنظیم کنیم ، چیه؟

من هنوز دقیقا متوجه نشدم که وقتی پروپرتیِ Style ئه Window را به مقدار DarkStyle تنظیم میکنیم ، چجور میشه که کنترل هایی که به عنوان فرزند اون Window تعریف کرده بودیم ، اتوماتیک استایل های داخل Resource ئه DarkStyle را میشناسن و اون استایل ها توی اون کنترل ها بصورت اتوماتیک سِت میشن؟

اینکه به DarkStyle دسترسی دارید صرفا به این خاطر ئه که منابع داخل StyleResource.xaml رو به Application.Resources اضافه کردید.

بله . جریان دسترسی را میدونم .

بالاخره DarkStyle یا باید Style پیشفرض رو داشته باشه یا نداشته باشه. اگر همچین وظیفه ای به عهده DarkStyle نیست نباید Style پیشفرض باشه.


DerivedStyles_3.rar

آها ، این ، DarkStyle هست که به عنوان استایل شناخته میشه؟
یعنی DarkStyle باید استایلِ پیش فرض برای CustomButton را توسط BaseOn برای خودش تعریف کنه . درسته؟

من فکر میکردم باید برای استایل ئه CustomButton ای که درون DarkStyle تعریف کرده بودیم ، مجددا یه استایل پیش فرض برای اون استایلِ CustomButton تعریف کنیم .بعد تعجب میکردم که اون استایلِ CustomButton ، خودش باید به عنوان استایل پیش فرض (مثل کد پروژه ی اول) محسوب بشه اما چرا در پروژه ی دوم برای این استایل ، مجددا باید استایل دیگه ای به عنوان استایل پیش فرض بنویسیم . پس اشتباه میکردم .

اما سئوالی که پیش میاد اینه که همونطور که در بالاتر پرسیده بودم ، پس چجوری میشه که با فراخونی استایلِ DarkStyle (به عنوان استایل Window) ، استایل هایی که در Resource ئه DarkStyle تعریف کرده بودیم ، شناسایی میشن و برای فرزندان Window بکار برده میشن؟
اگه میتونه شناسایی بشه ، پس چرا (مثل کد پروژه ی اول) ، به عنوان استایل پیش فرض نمیتونه بکار ببردش؟


------------------------------------------------------------------


خیلی ممنون از پروژه ای که درست کردین .
این جوری درست کردین که کدها ، عین پروژه ی اول هست . یعنی برخلاف پروژه ی دوم که استایل ها(ی کنترل های مختلف) ، به عنوان Resource در استایل دیگه (DarkStyle و ...) تعریف بشن ، بلکه هر کدوم از استایل های کنترل ها ، کلا در یک فایل xaml (بدون اینکه در Resource ئه استایل دیگه ای قرار بگیرن) ، تعریف میشن . و بجای تعریف 2 استایلِ DarkStyle و LightStyle ، میایم هر کدوم را درون یک فایل xaml مجزا تعریف میکنیم .

حالا این فایل xaml (که شامل استایل های مورد نظرمون هست) را در Resource ئه کنترل والد (مثلا Resource ئه Window) (بدیهی هست توسط MergedDictionaries) الحاق میکنیم (یعنی مثل کد زیر که نوشتید) :

XML:
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary x:Name="mysource" Source="DarkStyle.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

هر زمان هم که زمان اجرای برنامه ، در سی شارپ خواستیم استایل را عوض کنیم ، کافی هه Source ئه ResourceDictionary (در MergedDictionaries ئه ResourceDictionary ئه Window) را به اون فایل xaml (که استایل مورد نظرمون را توش تعریف کرده بودیم) تغییر بدیم .

Source ئه ResourceDictionary که یه شی URI میخواد و برای مقداردهی URI هم از دستور زیر پیروی میکنیم :

C#:
new Uri("/نام اسمبلی که معمولا همون نام فضای نام ای که ویندوز اصلی مون توش قرار داره هست;component/نام فایل xaml.xaml", UriKind.RelativeOrAbsolute);

بنابراین در این پروژه ای که دادین ، برای تغییر استایل ، کد زیر میشه :

C#:
        private void CustomButton_Click(object sender, RoutedEventArgs e)
        {
            this.Resources.MergedDictionaries[0].Source = new Uri("/DerivedStyles;component/LightStyle.xaml", UriKind.RelativeOrAbsolute);
        }


درست گفتم؟


پیشنهادی ندارم. اما به هر حال XML در جایی استفاده میشه که قراره داده در ساده ترین شکل ممکن و با ابتدایی ترین ویرایشگر ها قابل مشاهده و تغییر باشه، اگر نمیخواهید کسی اونها رو ببینه یا تغییر بده دیگه انتخاب XML منطقی نیست و مزیتی نداره.

پس به نظرتون اصلا نیازی به تامین امنیت فایل ای که تنظیمات را توش ذخیره میکنم ، هست؟
چون خود ویژال استودیو هم اگه اشتباه نکنم ، اطلاعات تنظیمات اش را در فایل xml ذخیره میکنه . درسته؟

حتما یک جای کار اشتباه کرده اید، گزینشی که نیست که بعضی ها رو اجرا کنه و بعضی ها رو نکنه.

من کد زیر را به متد Main در wpf اضافه میکنم :

C#:
    public partial class App : System.Windows.Application {
        private static System.Threading.Mutex SingleAppExecuteMutex;
        
        [System.STAThreadAttribute()]
        [System.Diagnostics.DebuggerNonUserCodeAttribute()]
        [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")]
        public static void Main() {
            // مشخص میکنه که آیا نخ ای (نخ جاری) که نام Mutex را مشخص میکنه ، مالک اولیه ی این Mutex محسوب بشه یا محسوب نشه .
            // نام Mutex ، به عنوان رشته ، در آرگومان دوم متد سازنده ی Mutex مشخص میشه .
            // در واقع مشخص میکنه که اولین نخ ای که نام Mutex را مشخص کرد ، اون نخ ، مالک اولیه ی Mutex باشه تا بتونه نخ های دیگه را از این نخ مالک ، مشخص کنه .
            bool isThreadNamedMutedOwner = true;
            // نام Mutex . این نام بصورت کاملا دلخواه هست و ربطی به نام پروسه ی برنامه نداره ولی ما برای نام با مصماتر ، برابر نام پروسه گرفتیم .
            string mutexName = "PoshtibangirTolo";
            // مشخص میکنه که آیا نخ جاری ای که Mutex را با نام ای که دادیم ، ایجاد کرد ، آیا مالک اولیه ی این Mutex هست یا اینکه نیست و Mutex ای با این نام ، قبلا توسط نخ دیگه ای ساخته شد؟
            // طبق توضیحات این آرگومان ، این فیلد را نباید مقداردهی اولیه کنیم
            bool isCreatingFirstMutex;
            App.SingleAppExecuteMutex = new System.Threading.Mutex(isThreadNamedMutedOwner, mutexName, out isCreatingFirstMutex);
            // اگه مالک اولیه ی این Mutex ، نخ جاری نبود . یعنی اگه یه بار دیگه این برنامه اجرا شد
            if (isCreatingFirstMutex == false)
            {
                // به کاربر پیام بده و برنامه را ببند .
                MessageBox.Show("این برنامه ، قبلا اجرا شد .");
                App.Current.Shutdown();
            }

            PoshtibangirTolo.App app = new PoshtibangirTolo.App();
            app.InitializeComponent();
            app.Run();
        }
    }

اما وقتی چندین بار برنامه ام را اجرا میکنم ، توی همه ی دفعات اجرا میشه و در اجرای بار دوم به بعد ، نه اون پیام MessageBox.Show را نشون میده و نه از برنامه بیرون میره . در صورتی که همین کد را اگه توی متد OnStartup (که در کلاس App اون را override کردم) بنویسم ، درست کار میکنه .

استاد ، توضیحاتی که برای متغییرهای مربوط به Mutex در کد بالا نوشتم (کامنت ها) ، توضیحات درستی هستن؟
کلا ، درک ام از Mutex (از جنبه ی اینکه برنامه فقط یکبار اجرا بشه) ، طبق توضیحاتی که در کد بالا نوشتم ، درسته؟

و اینکه اون متغییرِ مربوط به Mutex (متغییر سراسری استاتیک با نام SingleAppExecuteMutex) را نباید بصورت شی گرا (غیرِ استاتیک) تعریف کنیم . درسته؟
چون چندین نخ از چندین پروسه ی مختلف باید بهش دسترسی داشته باشن . درست میگم؟
بنابراین ، توی هیچ رویدادی هم نمیشه Dispose اش کرد . چون در پروسه و نخ های دیگه باید بهش دسترسی داشته باشن .
درست میگم؟


ببخشید طولانی شد استاد .
تشکر استاد :rose:
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلامی مجدد
استاد ، طبق پروژه ای که دادین ، فایل StyleResource.xaml که شامل DarkStyle و LightStyle بود را از هم جدا کردم و هر کدوم از این DarkStyle و LightStyle را توی فایل xaml ای ریختم (البته کار LightStyle را هنوز انجام ندادم) .

بعد توی app.xaml ، کد زیر را نوشتم :

XML:
    <Application.Resources>
        
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Resource\Style_Template\TemplateResource.xaml"/>
                <ResourceDictionary Source="Resource\Style_Template\DarkStyle.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
        
    </Application.Resources>

این کد ارور نمیده و همه چیز درست کار میکنه .
این فایل های xaml ، درون ریشه ی نرم افزار ، در پوشه ای بنام Resource که درونش پوشه ای بنام Style_Template وجود داره ، قرار دارن .
اما چه کد بالا را بنویسم یا نه ، درون Window.Resources ، نمیتونم الحاق کنم . یعنی کد زیر را که به Window اضافه میکنم ، ارور میده :

XML:
<Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="DarkStyle.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

چه مسیر کامل ، یعنی مسیر زیر را هم بنویسم ، باز هم ارور میده :

XML:
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Resource\Style_Template\DarkStyle.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

ارور زیر را میده :

کد:
An error occurred while finding the resource dictionary "Resource\Style_Template\DarkStyle.xaml".

ولی اگه کدِ Window.Resources را اضافه نکنم (فقط Application.Resources را اضافه کنم) ، حدودا مشکلی نداره (البته با یه اشکال که در زیر میگم) .

اون اشکال هم اینه که رنگ متن کنترل ShapeTextButton ، در شرایط و کدی کاملا برابر با حالت قبل (قبل از اینکه استایل های DarkStyle و LightStyle را درون فایل xaml ئه مجزایی انتقال بدم) ، حتی با تغییر رنگ متن پروپرتی های مربوطه (پروپرتی هایی که برای تغییر رنگ های متن برای رویدادهای مختلف در نظر گرفته شد) ، باز رنگ متن اش تغییر نمیکنه (این مشکل فقط زمان اجرا هست و زمان xaml designer این مشکل نیست) .

مثل تغییر مقدار پروپرتی Foreground ئه ShapeTextButton که برای تغییر رنگ متن در حالت عادی هست (که این تغییر رنگ ، از زمانی که استایل ها را به فایل جدید xaml منتقل کردم ، زمان اجرای برنامه ، انجام نمیشه) (متن که میگم ، همون پروپرتی Content هست که در ShapeTextButton فقط به عنوان string در نظر گرفتم هر چند از نوع object هست) .

کدهای تمپلیت هم با اونکه اصلا تغییری نکردن و همون هستن ولی اندک (بخشی از) کدِ تمپلیت ای که به این قضیه مربوط میشن ، اینه :

XML:
    <CustomControls:ShapeTextButton x:Key="HasValue_Converter"/>

    <ControlTemplate x:Key="ShapeTextButtonTemplate" TargetType="{x:Type CustomControls:ShapeTextButton}">
        <Grid Name="MainGrid" Background="Transparent">
            <Path Name="Shape" Focusable="False"
                    Data="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=DefaultButtonShape.Data}"                    Stroke="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=DefaultButtonShape.Stroke}"
                    StrokeThickness="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=DefaultButtonShape.StrokeThickness}"
                    Fill="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=DefaultButtonShape.Fill}" />
                    
            <ContentPresenter x:Name="ContentPresenter" TextBlock.Foreground="{TemplateBinding Foreground}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="{TemplateBinding Padding}"/>
        </Grid>
        
                <ControlTemplate.Triggers>
                            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsMouseOver}" Value="true"/>
                    <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=MouseEnterContentBrush, Converter={StaticResource HasValue_Converter}}" Value="true"/>
                </MultiDataTrigger.Conditions>
                <MultiDataTrigger.Setters>
                    <Setter TargetName="ContentPresenter" Property="TextBlock.Foreground" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=MouseEnterContentBrush}"/>
                </MultiDataTrigger.Setters>
            </MultiDataTrigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

اون کلید HasValue_Converter هم کد متدش :

C#:
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {           
        return value != null;
        }


میدونین بخاطر چی میتونه باشه؟
تشکر استاد .
 

the_king

مدیرکل انجمن
خیلی ممنون استاد از جواب کامل تون :rose:
بله . مفهومی که از استایل پیش فرض توی ذهنم شکل گرفته بود این بود که استایلی باشه که Setter نداشته باشه که اشتباه بود . متوجه شدم .
اگه اشتباه نکنم ، استایل پیش فرض ، به اولین استایل برای اون نوع داده ای که بنویسیم ، استایل پیش فرض محسوب میشه . درسته؟
بله.

فرق اینکه Resource ای در اون Window مشخص کنیم یا پروپرتیِ Style ئه اون ویندوز را (به DarkStyle و ...) مشخص و تنظیم کنیم ، چیه؟
Resource ای که برای Window مشخص کنید منبعی برای اون پنجره و فرزندانش محسوب میشه، پس هر چیزی که داخلش توصیف کنید فرضا یک Style میتونه مورد استفاده اون پنجره و فرزندانش باشه. این منابع الزاما Style نیستند و استفاده از منابع هم حالت کلی داره.

اما Style ای برای اون پنجره مشخص می کنید برای اون پنجره و فرزندانش قابل استفاده است به این دلیل که Style شونه، اما دیگه منابع داخل Style ئه صرفا برای خود Style ئه قابل دسترسی ئه. اگر در اون Style ئه یک Style ای برای Button به عنوان منبع مشخص کردید، به این خاطر روی دکمه های فرزند اون پنجره اعمال میشه که جزئی از Style پنجره است، نه به این خاطر که پنجره به اون منبع Style دکمه دسترسی داره. خود Style پنجره است که برای دکمه Style ارائه کرده، نه اینکه پنجره خودش بره داخل منابع Style دنبال Style برای دکمه بگرده.

من هنوز دقیقا متوجه نشدم که وقتی پروپرتیِ Style ئه Window را به مقدار DarkStyle تنظیم میکنیم ، چجور میشه که کنترل هایی که به عنوان فرزند اون Window تعریف کرده بودیم ، اتوماتیک استایل های داخل Resource ئه DarkStyle را میشناسن و اون استایل ها توی اون کنترل ها بصورت اتوماتیک سِت میشن؟
وظیفه اون فرزندان نیست که برای خودشون Style ست کنند. Style ای که برای پنجره اعمال کرده اید برای همه اون فرزندان پنجره که Style اختصاصی ندارند میتونه Style اعمال کنه، به شرطی که از عهده اش بر بیاد. خود Style ئه است که بررسی می کنه تا ببینه میتونه برای اون فرزندان Style با نوع مناسب بده یا نه.
اگه نتونست که هیچی، ولی اگر تونست Style میده. خود فرزندان نیستند که دنبال Style میگردند.

آها ، این ، DarkStyle هست که به عنوان استایل شناخته میشه؟
یعنی DarkStyle باید استایلِ پیش فرض برای CustomButton را توسط BaseOn برای خودش تعریف کنه . درسته؟
در چیزی که شما نوشته بودید پیشفرض بود، چون کلید با نام مشخصی نداشت.
استایل پیشفرض که نیازی به BasedOn نداره.

بله. ولی تا حد امکان از اینجور تعیین صریح مسیر و Hard coding خودداری کنید. اینجور اتکا کردن روی یک مقدار هم نگهداری و هم سازگاری رو تضعیف می کنه.

پس به نظرتون اصلا نیازی به تامین امنیت فایل ای که تنظیمات را توش ذخیره میکنم ، هست؟
چون خود ویژال استودیو هم اگه اشتباه نکنم ، اطلاعات تنظیمات اش را در فایل xml ذخیره میکنه . درسته؟
نیاز رو شما برای برنامه تون تعیین می کنید، نه من. ویژوال استدیو نمیخواد تنظیماتش مخفی بشه، بر عکس میخواد به ساده ترین شکل ممکن قابل ویرایش باشه.

من کد زیر را به متد Main در wpf اضافه میکنم :

C#:
    public partial class App : System.Windows.Application {
        private static System.Threading.Mutex SingleAppExecuteMutex;
       
        [System.STAThreadAttribute()]
        [System.Diagnostics.DebuggerNonUserCodeAttribute()]
        [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")]
        public static void Main() {
            // مشخص میکنه که آیا نخ ای (نخ جاری) که نام Mutex را مشخص میکنه ، مالک اولیه ی این Mutex محسوب بشه یا محسوب نشه .
            // نام Mutex ، به عنوان رشته ، در آرگومان دوم متد سازنده ی Mutex مشخص میشه .
            // در واقع مشخص میکنه که اولین نخ ای که نام Mutex را مشخص کرد ، اون نخ ، مالک اولیه ی Mutex باشه تا بتونه نخ های دیگه را از این نخ مالک ، مشخص کنه .
            bool isThreadNamedMutedOwner = true;
            // نام Mutex . این نام بصورت کاملا دلخواه هست و ربطی به نام پروسه ی برنامه نداره ولی ما برای نام با مصماتر ، برابر نام پروسه گرفتیم .
            string mutexName = "PoshtibangirTolo";
            // مشخص میکنه که آیا نخ جاری ای که Mutex را با نام ای که دادیم ، ایجاد کرد ، آیا مالک اولیه ی این Mutex هست یا اینکه نیست و Mutex ای با این نام ، قبلا توسط نخ دیگه ای ساخته شد؟
            // طبق توضیحات این آرگومان ، این فیلد را نباید مقداردهی اولیه کنیم
            bool isCreatingFirstMutex;
            App.SingleAppExecuteMutex = new System.Threading.Mutex(isThreadNamedMutedOwner, mutexName, out isCreatingFirstMutex);
            // اگه مالک اولیه ی این Mutex ، نخ جاری نبود . یعنی اگه یه بار دیگه این برنامه اجرا شد
            if (isCreatingFirstMutex == false)
            {
                // به کاربر پیام بده و برنامه را ببند .
                MessageBox.Show("این برنامه ، قبلا اجرا شد .");
                App.Current.Shutdown();
            }

            PoshtibangirTolo.App app = new PoshtibangirTolo.App();
            app.InitializeComponent();
            app.Run();
        }
    }

اما وقتی چندین بار برنامه ام را اجرا میکنم ، توی همه ی دفعات اجرا میشه و در اجرای بار دوم به بعد ، نه اون پیام MessageBox.Show را نشون میده و نه از برنامه بیرون میره . در صورتی که همین کد را اگه توی متد OnStartup (که در کلاس App اون را override کردم) بنویسم ، درست کار میکنه .
یک جای کار اشتباهه، باید ببینید App.xaml و App.xaml.cs چه شرایطی دارند که با Main مشکل دارید.
من اطلاعی ندارم که شما بر اساس کدوم راهنما عمل کرده اید و یا پروژه تون چه تنظیماتی داره.

استاد ، توضیحاتی که برای متغییرهای مربوط به Mutex در کد بالا نوشتم (کامنت ها) ، توضیحات درستی هستن؟
کلا ، درک ام از Mutex (از جنبه ی اینکه برنامه فقط یکبار اجرا بشه) ، طبق توضیحاتی که در کد بالا نوشتم ، درسته؟
بله.

و اینکه اون متغییرِ مربوط به Mutex (متغییر سراسری استاتیک با نام SingleAppExecuteMutex) را نباید بصورت شی گرا (غیرِ استاتیک) تعریف کنیم . درسته؟
نه. اصلا ربطی اون نداره، static ئه چون دارید در متد static استفاده اش می کنید. در متد static که فیلد غیر static ندارید.
اگه هزار تا غیر static اش رو هم میساختید شی در اصل یکی بود که اونم سیستم عامل تحویل میده و ربطی به static بودن و نبودن متغیر نداره.

چون چندین نخ از چندین پروسه ی مختلف باید بهش دسترسی داشته باشن . درست میگم؟
بی ربط ئه، یک فیلد غیر static میتونه توسط نخ های متفاوت دسترسی داشته باشه و فیلد static داخل پروسه هم هیچ ربطی به پروسه های دیگه نداره.
قبلا در مورد Mutex توضیح داده بودم، اشتراکش ربط به static بودنش نداره.

بنابراین ، توی هیچ رویدادی هم نمیشه Dispose اش کرد . چون در پروسه و نخ های دیگه باید بهش دسترسی داشته باشن .
درست میگم؟
ارتباطی نداره، Disposable هم هست.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
خیلی ممنون استاد از توضیح کامل تون :rose:
بی زحمت ، جواب پست قبلی هم میدین؟
ببخشیدها
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
شما در پروژه تون طبعا مسیری بکار برده اید که اشتباهه. پروژه هم پیش شما است، نه من.
در مورد Trigger ها هم ایده ای ندارم.

خیلی ممنون استاد .
کدها ، همونی هه که قبلا کدهای استایل ها را در چند پست قبل داده بودم .
به جای خاصی هم مشکوک نیستم (بجز همون کدها که در پست قبل داده بودم که انگار مشکلی نداره) تا اینکه کدها را در ابعاد کوچیک تر تست کنم .

استاد ، در پست 566 که پروژه را پیوست کردین ، اون پروژه ، از Style ها بصورت مستقیم استفاده میکنه .
حالا نمیتونین کاری کنین که پروژه ی دومی که در پست 565 داده بودم که استایل ها ، درونِ Resource ئه استایلِ دیگه ای بودن ، به این روش کدی نوشت که استایل ها بصورت تو در تو (Derived) کار کنن؟ (یعنی مثل پروژه ی اول که داده بودم ، کار کنن) ؟
متوجه ی منظورم شدید؟

تشکر استاد .
 

the_king

مدیرکل انجمن
استاد ، در پست 566 که پروژه را پیوست کردین ، اون پروژه ، از Style ها بصورت مستقیم استفاده میکنه .
بصورت مستقیم؟ در پروژه پیوستی ام کدوم المنت از کدوم Style بصورت مستقیم استفاده می کنه؟ مشخصش کنید.

حالا نمیتونین کاری کنین که پروژه ی دومی که در پست 565 داده بودم که استایل ها ، درونِ Resource ئه استایلِ دیگه ای بودن ، به این روش کدی نوشت که استایل ها بصورت تو در تو (Derived) کار کنن؟ (یعنی مثل پروژه ی اول که داده بودم ، کار کنن) ؟
متوجه ی منظورم شدید؟
اولا تو در تو چه ربطی داره به Derived؟ به دیکشنری یک مراجعه بکنید.
در گوگل "WPF "Derived Style رو جستجو کنید ببینید چی رو براتون میاره، Style.BasedOn، همون چیزی که براتون مثال زدم.
ثانیا شما در پروژه اول روش معرفی نکرده اید. در پروژه ای که من براتون مثال زدم Style ها Derived شدن، براتون که توضیح دادم اشتباه کار تون در چیه.
شما ببینید این چیزی که میگید روش، در کجا مثال براش هست؟ اگه مثال هست که دیگه مساله حل شده است.
ثالثا کسی نمیتونه برای حل مساله ای برای من روش تعیین کنه، روش رو من خودم تعیین می کنم، روش مورد علاقه بقیه هم به من ربطی نداره.
نمیتونین کاری کنین سوال کسی است که میخواد منو استخدام کنه؟ یا خودتون رو کارفرما فرض کرده اید؟
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بصورت مستقیم؟ در پروژه پیوستی ام کدوم المنت از کدوم Style بصورت مستقیم استفاده می کنه؟ مشخصش کنید.


اولا تو در تو چه ربطی داره به Derived؟ به دیکشنری یک مراجعه بکنید.
در گوگل "WPF "Derived Style رو جستجو کنید ببینید چی رو براتون میاره، Style.BasedOn، همون چیزی که براتون مثال زدم.
ثانیا شما در پروژه اول روش معرفی نکرده اید. در پروژه ای که من براتون مثال زدم Style ها Derived شدن، براتون که توضیح دادم اشتباه کار تون در چیه.
شما ببینید این چیزی که میگید روش، در کجا مثال براش هست؟ اگه مثال هست که دیگه مساله حل شده است.
ثالثا کسی نمیتونه برای حل مساله ای برای من روش تعیین کنه، روش رو من خودم تعیین می کنم، روش مورد علاقه بقیه هم به من ربطی نداره.
نمیتونین کاری کنین سوال کسی است که میخواد منو استخدام کنه؟ یا خودتون رو کارفرما فرض کرده اید؟

خیلی ممنون استاد .
حدودا فهمیدم مشکل از کجا آب میخوره اما دلیل اش و هم اینکه راه حل اش را هنوز متوجه نشدم .

در کد زیر (که بخشی از تمپلیت ئه ShapeTextButton نوشتم) :

XML:
<ContentPresenter x:Name="ContentPresenter" TextBlock.Foreground="Red"/>

حتی اگه مستقیم هم مقدار TextBlock.Foreground را عوض کنیم ، رنگ متن (محتوا که به عنوان متن در نظر گرفتم) ، اصلا تغییری نمیکنه .
همونطور که قبلا گفتم ، این مشکل (ست نشدن مقدار پروپرتی TextBlock.Foreground برای متن محتوا) ، زمانی پیش میاد که اگه استایل ئه ShapeTextButton بصورت مستقل نوشته بشه (مثل پروژه ی سوم که فایل DarkStyle.xaml را نوشتید) اما اگه همین استایلِ نوشته شده برای ShapeTextButton (با همین تمپلیت) را در Resource ئه Style ئه دیگه تعریف کنم ، هیچ مشکلی نیست و مقدار پروپرتیِ TextBlock.Foreground ، هر چی که بدیم ، درست روی متن محتوا ست میشه !

چرا در این دو حالت (که کدها هم دقیقا یکسان هستند فقط مکان استایل ها تغییر میکنه) ، در یک حالتش کار میکنه و در یک حالت دیگه ، نه؟
و در حالتی که کار نمیکنه (استایل را در فایل DarkStyle.xaml بصورت مستقیم تعریف کرده بودیم) ، در این حالت ، آیا میشه برای تنظیم رنگ و بِراش برای متن محتوا ، بجای TextBlock.Foreground ، کار دیگه ای کرد؟
اگه آره ، چه کاری؟

تشکر استاد . :rose:
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
خیلی ممنون استاد .
حدودا فهمیدم مشکل از کجا آب میخوره اما دلیل اش و هم اینکه راه حل اش را هنوز متوجه نشدم .

در کد زیر (که بخشی از تمپلیت ئه ShapeTextButton نوشتم) :

XML:
<ContentPresenter x:Name="ContentPresenter" TextBlock.Foreground="Red"/>

حتی اگه مستقیم هم مقدار TextBlock.Foreground را عوض کنیم ، رنگ متن (محتوا که به عنوان متن در نظر گرفتم) ، اصلا تغییری نمیکنه .
همونطور که قبلا گفتم ، این مشکل (ست نشدن مقدار پروپرتی TextBlock.Foreground برای متن محتوا) ، زمانی پیش میاد که اگه استایل ئه ShapeTextButton بصورت مستقل نوشته بشه (مثل پروژه ی سوم که فایل DarkStyle.xaml را نوشتید) اما اگه همین استایلِ نوشته شده برای ShapeTextButton (با همین تمپلیت) را در Resource ئه Style ئه دیگه تعریف کنم ، هیچ مشکلی نیست و مقدار پروپرتیِ TextBlock.Foreground ، هر چی که بدیم ، درست روی متن محتوا ست میشه !

چرا در این دو حالت (که کدها هم دقیقا یکسان هستند فقط مکان استایل ها تغییر میکنه) ، در یک حالتش کار میکنه و در یک حالت دیگه ، نه؟
و در حالتی که کار نمیکنه (استایل را در فایل DarkStyle.xaml بصورت مستقیم تعریف کرده بودیم) ، در این حالت ، آیا میشه برای تنظیم رنگ و بِراش برای متن محتوا ، بجای TextBlock.Foreground ، کار دیگه ای کرد؟
اگه آره ، چه کاری؟

تشکر استاد . :rose:

البته یه راهی که فعلا به ذهنم میرسه اینه که بجای ContentPresenter ، از ContentControl استفاده کنم (و Foreground ئه ContentControl را تنظیم کنم) اما اصولی نیست .
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
خیلی ممنون استاد .
حدودا فهمیدم مشکل از کجا آب میخوره اما دلیل اش و هم اینکه راه حل اش را هنوز متوجه نشدم .

در کد زیر (که بخشی از تمپلیت ئه ShapeTextButton نوشتم) :

XML:
<ContentPresenter x:Name="ContentPresenter" TextBlock.Foreground="Red"/>

حتی اگه مستقیم هم مقدار TextBlock.Foreground را عوض کنیم ، رنگ متن (محتوا که به عنوان متن در نظر گرفتم) ، اصلا تغییری نمیکنه .
همونطور که قبلا گفتم ، این مشکل (ست نشدن مقدار پروپرتی TextBlock.Foreground برای متن محتوا) ، زمانی پیش میاد که اگه استایل ئه ShapeTextButton بصورت مستقل نوشته بشه (مثل پروژه ی سوم که فایل DarkStyle.xaml را نوشتید) اما اگه همین استایلِ نوشته شده برای ShapeTextButton (با همین تمپلیت) را در Resource ئه Style ئه دیگه تعریف کنم ، هیچ مشکلی نیست و مقدار پروپرتیِ TextBlock.Foreground ، هر چی که بدیم ، درست روی متن محتوا ست میشه !

چرا در این دو حالت (که کدها هم دقیقا یکسان هستند فقط مکان استایل ها تغییر میکنه) ، در یک حالتش کار میکنه و در یک حالت دیگه ، نه؟
و در حالتی که کار نمیکنه (استایل را در فایل DarkStyle.xaml بصورت مستقیم تعریف کرده بودیم) ، در این حالت ، آیا میشه برای تنظیم رنگ و بِراش برای متن محتوا ، بجای TextBlock.Foreground ، کار دیگه ای کرد؟
اگه آره ، چه کاری؟

تشکر استاد . :rose:

خیلی ممنون استاد . :rose:
متوجه شدم .
در استایل ها ، برای نوع TextBlock هم استایلی تعریف کرده بودم . تعریف کردنِ این استایل باعث میشد تا کد TextBlock.Foreground در کد بالا (که در تمپلیتِ ShapeTextButton تعریف کرده بودم) ، از Foreground ای که برای اون استایلِ TextBlock تعیین کرده بودم ، استفاده کنه .
باید استایلِ تعریف شده در TextBlock را یا حذف کنم یا کلید براش بذارم .

ای کاش یه ابزار یا چیزی طراحی میکردن که همونطور میتونیم برای کدهای سی شارپ بریک پوینت بذاریم و تریس شون کنیم ، کدهای xaml را هم میتونستیم تریس کنیم تا از این مشکلاتی که پیش میاد را خیلی راحت تر پیدا کنیم . این جور مشکلات ، منو یاد دیباگر اتوپلی میندازه :green: . البته نمیخوام ربطی بین شون برقرار کنم . میدونم زمان طراحی ، طراحی چیزی بنامچیزی که کد را تریس کنه ، حداقل برای دانش امروزی ، غیر ممکنه .
تشکر استاد .
 
آخرین ویرایش:

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلامی مجدد استاد .
استاد ، توی همون فایل DarkStyle.xaml ، یه استایلی برای نوع Window تعریف کردم (هیچ کلیدی براش در نظر نگرفتم) .
این فایل را هم درون ResourceDictionary.MergedDictionaries ئه Application ام لود کردم .
اما در window ام ، بصورت عادی کار نمیکنه . حتما باید استایل اش را بصورت مستقیم ، مقدار بدم تا کار کنه (این جوری) :

XML:
Style="{StaticResource {x:Type Window}}"

اگه کد بالا را درون Window ام بدم ، کار میکنه (حالا StaticResource یا DynamicResource بودنش مهم نیست) . اما اگه این استایل را مشخص نکنم ، اصلا کار نمیکنه و استایل ای که برای ویندوز مشخص کرده بودم ، کار نمیکنه . چرا؟

این در صورتی هه که هر استایلِ دیگه ای که برای انواع المنت و کنترل های دیگه درون DarkStyle.xaml ام مشخص کرده بودم (اون هایی که بهشون کلید نداده بودم) ، کار میکنن و لازم به کدی بالا برای انتخاب صریح استایل ، نیست .
تشکر استاد .
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
همچنین استاد ، مثلا من فایل های xaml ام (از استایل و تمپلیت گرفته تا هر نوع فایل xaml ام) را داخل پوشه ی برنامه ام تعیین مکان کردم . یعنی داخل پوشه ی Bin>Debug ، تعیین مکان نکردم .
پس چطور میشه که وقتی فقط پوشه ی Debug ام را جای دیگه ای کپی میکنم (محتویات فایل های xaml را همراش کپی نمیکنم) ، اما با این حال ، درست همه ی اون فایل های xaml را اجرا میکنه . اصلا فایل xaml ام توش نبوده ، پس از کجا ، درست همون فایل ها را شناسایی میکنه؟
تشکر استاد .
 

the_king

مدیرکل انجمن
سلامی مجدد استاد .
استاد ، توی همون فایل DarkStyle.xaml ، یه استایلی برای نوع Window تعریف کردم (هیچ کلیدی براش در نظر نگرفتم) .
این فایل را هم درون ResourceDictionary.MergedDictionaries ئه Application ام لود کردم .
اما در window ام ، بصورت عادی کار نمیکنه . حتما باید استایل اش را بصورت مستقیم ، مقدار بدم تا کار کنه (این جوری) :

XML:
Style="{StaticResource {x:Type Window}}"

اگه کد بالا را درون Window ام بدم ، کار میکنه (حالا StaticResource یا DynamicResource بودنش مهم نیست) . اما اگه این استایل را مشخص نکنم ، اصلا کار نمیکنه و استایل ای که برای ویندوز مشخص کرده بودم ، کار نمیکنه . چرا؟
نمیدونم چرا از من سوال می کنید. پروژه شما پیوست سوال تون هست؟ نیست. پس باید از کسی بپرسید که به پروژه دسترسی داره.

همچنین استاد ، مثلا من فایل های xaml ام (از استایل و تمپلیت گرفته تا هر نوع فایل xaml ام) را داخل پوشه ی برنامه ام تعیین مکان کردم . یعنی داخل پوشه ی Bin>Debug ، تعیین مکان نکردم .
پس چطور میشه که وقتی فقط پوشه ی Debug ام را جای دیگه ای کپی میکنم (محتویات فایل های xaml را همراش کپی نمیکنم) ، اما با این حال ، درست همه ی اون فایل های xaml را اجرا میکنه . اصلا فایل xaml ام توش نبوده ، پس از کجا ، درست همون فایل ها را شناسایی میکنه؟
تشکر استاد .
فایل های xaml تون رو اجرا می کنه؟ شما بعد این همه توضیحات مکرر همچنان فکر می کنید فایل های xaml اجرایی هستند؟
از اون گذشته قبلا در مورد اینکه فایل های xaml به چی تبدیل می شوند توضیح داده بودم.
فایل اجرایی برنامه شما بعد کامپایل هیچ کاری به فایل های cs. و xaml. و csproj. و ... پروژه نداره، وقتی به اون فایل ها کاری نداشته باشه طبعا مسیر فایل شون هم اهمیتی نداره. دلیل اینکه چرا فایل اجرایی دیگه کاری با فایل های منبع پروژه نداره رو هم که لابد خودتون میدونید.
 

جدیدترین ارسال ها

بالا