پرچمداران

  1. Ramtin

    Ramtin

    مدیر کل


    • امتیاز: پسندیدن

      469

    • تعداد ارسال ها

      240


  2. RaminMT

    RaminMT

    مدیر کل


    • امتیاز: پسندیدن

      332

    • تعداد ارسال ها

      204


  3. Hesamom

    Hesamom

    توسعه دهنده


    • امتیاز: پسندیدن

      267

    • تعداد ارسال ها

      150


  4. ryco

    ryco

    مدیر کل


    • امتیاز: پسندیدن

      249

    • تعداد ارسال ها

      243



مطالب محبوب

در حال نمایش بیشترین مطالب پسند شده از زمان دوشنبه, 16 شهریور 1394 در همه بخش ها

  1. 8 پسند
    با سلام در این آموزش با مقدمات برنامه نویسی کراس پلتفرم (مالتی پلتفرم) با استفاده از Xamarin.Forms در خدمت شما هستم . فرض این آموزش بر این هست که شما برنامه نویسی به زبان سی شارپ (C# .Net) را از پیش فرا گرفته اید و آشنایی حداقلی با HTML یا XAML دارید . بنا به دلیل اینکه منابع موجود برای پرسش و پاسخ از Xamarin کمتر از منابع موجود برای Native پلتفرم ها میباشد ابتدا حتماً بر روی یکی از زبان های مبتنی بر سی شارپ تسلط داشته باشید . به دلیل شباهت بیشتر ترجیحاً یکی از این زبان ها / سیستم عامل ها را انتخاب کنید : UWP / WPF / Windows Phone Silverlight / Windows Runtime در این آموزش از Visual Studio 2017 و شبیه ساز اندروید مایکروسافت استفاده شده است . در قسمت اول آموزش به سراغ تنظیم امولاتور خواهیم رفت تا شبیه ساز دسترسی به اینترنت داشته باشد و پس آن به آموزش خواهیم پرداخت . امیدوارم که این آموزش مورد توجهتون قرار بگیره . » پیوند های مرتبط « آموزش نصب و راه اندازی زامارین با شبیه ساز مک آموزش تنظیم Visual Studio Emulator for Android جهت دسترسی به اینترنت (پست شماره #2 همین مطلب)
  2. 8 پسند
    آموزش برنامه نویسی با Xamain.Forms قسمت سوم : ساخت اولین پروژه (ماشین حساب) از منوی ساخت پروژه جدید ویزوال استدیو به قسمت مشخص شده بروید و یک پروژه جدید با نام دلخواه بسازید . توجه داشته باشید از اسامی بسیار کوتاه استفاده کنید یا آدرس محل ذخیره سازی پروژه را به محلی مانند C:\XamFormProjs تغییر دهید چون در غیر اینصورت در حین بیلد کردن پروزه و ساخت خروجی به خطاهای بسیار زیادی از جمله طولانی شدن آدرس یک فایل بر خواهید خورد که مجبور به تغییر نام پوشه یا انتقال آن به محلی دیگر هستید ! (خلاصه پیشگیری بهتر از درمانه !) سپس با زدن کلید OK پنجره ی دیگری که برای شما باز میشود به صورت پیشفرض روی حالت Xamarin Forms و Blank App تنظیم شده که آن ها را بدون تغییر باقی بگذارید . گزینه code sharing strategy نیز به این اشاره دارد که پروژه مشترک بین هر سه سیستم عامل از نوع کلاس پرتابل باشد یا Shared project که از نوع پیشفرض یعنی Shared Project استفاده مینمائیم و ok را میزنیم تا پروژه ساخته شود . در حین ساخت پروژه ممکن است سوالاتی در ارتباط با Minimum os version و Target platform از شما پرسیده شود که آن ها را به دلخواه تنظیم کنید . یکی از بهترین حالات این است که حداقل ورژن سیستم عامل را روی پایین ترین ورژن موجود در لیست تنظیم کنید و Target را روی جدیدترین ورژن SDK تنظیم کنید . پس از ساخته شدن کامل پروژه روی پروژه اصلی (Solution) که در آن 4 پروژه دیگر وجود دارد راست کلیک کنید و Manage NuGet package for solution را بزنید . حال در بخش Updates تیک گزینه Select all packages را بزنید و سپس کلید Update را بزنید تا همه Nuget ها به یک باره آپدیت شوند .سپس احتمالاً ویژوال استدیو از شما میخواهد یک بار برنامه را ریست کنید این کار را انجام دهید . در اجرای مجدد پس از آپدیت شدن همه نوگت ها احتمالاً تعدادی نوگت جدید اضافه خواهد شد مانند Xamarin.Build.Download که آن ها را نیز آپدیت نمائید و در صورت نیاز نیز ویژوال استدیو را مجدداً ریست کنید تا احتمال خطا در حین انجام کار کمتر شود . حال یک بار سولوشن را Rebuild کنید . (Debug , Any CPU, Android) پس از پایان یافتن ریبیلد در پروژه Shared فایل MainPage.XAML را اجرا نمائید و سعی کنید داخل تگ ContentPage یک تگ مانند Label بسازید . اگر ساجسشن های ویژوال استدیو به درستی نمایش داده شد و توانستید تگ Label را پیدا کنید که مشکلی نیست اما در غیر اینصورت باید از ویژوال استدیو و زمارین تشکر کرد ! در این حالت ابتدا یک پوشه به نام View در پروژه Shared ایجاد نمائید . سپس روی پوشه راست کلیک کنید Add -> New item را بزنید . حال یک Content Page با نام دلخواه ایجاد کنید و در پوشه View اضافه نمائید . حال فایل جدید باید بدون مشکل قابلیت ساجست را داشته باشد ! فایل MainPage قبلی که در روت پروژه قرار دارد را حذف کنید و سپس فایل App.XAML.Cs را باز کنید و در کانستراکتور App پس از InitializeComponent() به فایلی که ساختید رفرنس دهید . حال پروژه شما به یک پروژه صحیح بدون مشکل تبدیل شد . حال پس از تصحیح پروژه در ادامه اولین پروژه را خواهیم ساخت . این آموزش ادامه دارد ...
  3. 8 پسند
    آموزش برنامه نویسی با Xamain.Forms قسمت دوم: معرفی انواع صفحات در زمارین فرم در این قسمت قصد داریم با انواع صفحات موجود در زمارین فرم آشنا شویم. تعدادی از انواع پر استفاده تر این صفحات: Content Page Master Detail Page Navigation Page Tabbed Page نوع اول یعنی Content Page یک صفحه خالی و بسیار ساده است که میتوانید از آن برای نمایش محتوا به کاربر ستفاده کنید. این نوع صفحه در اکثر زبان های برنامه نویسی و قالب ها به عنوان Blank Page نیز شناخته میشود. نوع دوم یعنی Master Details Page یکی از انواع پر کاربرد صفحات است که این نوع صفحه شامل منوی همبرگری به صورت پیشفرض بوده و همچنین عنوان صفحه میباشد. این نوع صفحه به صورت خودکار Navigation های کاربر را مدیریت میکند و همانطور که گفته شد شامل منوی همبرگری قابل سوایپ در اندروید میباشد. Navigation خودکار به ین معنیست که در صورت تغییر صفحه برنامه خود Xamarin به صورت خودکار کلید برگشت را مدیریت خواهد کرد. نوع سوم یعنی Navigation Page نیز دقیقاً مانند Master Detail Page میباشد با این تفاوت که دارای منوی همبرگری نمیباشد. نوع چهارم صفحات یعنی Tabbed Page صفحه ای میسازد که به صورت تب بوده و مشابه Pivot در UWP میباشد. در قسمت بعدی آموزش با آموزش ساخت یک برنامه ماشین حساب بسیار ساده در خدمت شما خواهیم بود. در قسمت دوم آموزش از Content Page استفاده خواهیم کرد که ساده ترین نوع صفحه است. در قسمت های بعدی با انواع دیگر صفحات بیشتر آشنا خواهیم شد.
  4. 8 پسند
    قسمت اول : آموزش تنظیم Visual Studio Emulator for Android جهت دسترسی به اینترنت ابتدا در استارت منو (یا کرتانا) عبارت Hyper-V Manager را جستجو کنید و برنامه را اجرا کنید . در محیط Hyper-V Manager به قسمت Virtual Switch Manager بروید . در پنجره ای که باز میشود در قسمت سمت راست گزینه External را انتخاب کنید و سپس روی Create Virtual Switch کلیک کنید . سپس در لیست Virtual Switches یک سوئیچ جدید اضافه شده که وارد آن شوید . حال پنجره را Apply و ok کنید تا بسته شود . سپس در صفحه اصلی Hyper-v Manager در قسمت Virtual Machines ماشین مجازی مد نظر خود را انتخاب روی آن راست کلیک نمائید و سپس به قسمت Settings آن بروید . در صورتی که ماشین مجازی مورد نظر را یافت نمیکنید توجه داشته باشید که حتماً یک بار باید ماشین مجازی شما اجرا شده باشد ، در غیر اینصورت در این لیست ظاهر نخواهد شد . در پنجره باز شده در قسمت add hardware گزینه Network Adapter را انتخاب کنید و آنرا Add کنید . حال در لیست سخت افزار ها Network Adapter را انتخاب نمائید و در تنظیمات شبکه Virtual Switch ی که در مراحل قبل ساختید را انتخاب کنید . در صورتیکه چندین virtual switch ایجاد نمودید اینجا نیز به تعداد virtual switch ها Network Adapter بسازید و در هر کدام یکی از سوئیچ ها را انتخاب کنید . حالا پنجره را اوکی کنید و کار تمام است . حالا پس از اجرای امولاتور باید بتوانید از اینترنت استفاده نمایئد .
  5. 7 پسند
    سلام وقت بخیر، از اونجا که برای دوست عزیزمون بهروز برای پخش موزیک یا ویدیو در پس زمینه مشکل ایجاد شده، فکر کردم این آموزش رو بذارم برای دوستانی که مشکلی مشابه دارند. نکته: من ویژوال استودیو روی کامپیوترم ندارم پس شاید بعضی از کدهام اشتباه تایپی داشته باشند، پس خودتون با Intellisense ویژوال استودیو اون رو درست کنید. خب پروژه جدیدی از نوع یکپارچه با ورژن SDK نسخه 10.0.14393 به نام WN_BackgroundPlayback ایجاد نمایید. درون این پروژه یک کلاس اضافه کنید و کدهای زیر رو درون اون بنویسید: using Windows.Media.Playback; // in code az sample e MS copy shode namespace WN_BackgroundPlayback { class PlaybackService { // sakhte intanse az class static PlaybackService instance; public static PlaybackService Instance { get { if (instance == null) instance = new PlaybackService(); return instance; } } // har appi mitone ye MediaPlayer dashte bashe ke dar tamame safhat mitone azash estefade kone public MediaPlayer Player { get; private set; } public PlaybackService() { // yadeton bashe hamishe AutoPlay ro false bezarin ta moshkeli baraton pish nayad Player = new MediaPlayer {AutoPlay = false}; } } } سپس این کلاس رو ذخیره کنید و آنرا ببندید. حال فایل Package.appxmanifest را با CodeViewer باز کنید (اگه اشتباه نکنم روش راست کلیک که کنید دومین گزینه باید این فایل رو بصورت xml براتون باز کنه) خب اینجا درون تگِ Capabalities کد زیر را بنویسید: <uap3:Capability Name="backgroundMediaPlayback" /> که کد کلی باید بدین صورت باشد: <Capabilities> <Capability Name="internetClient" /> <uap3:Capability Name="backgroundMediaPlayback" /> </Capabilities> حال صفحه را ذخیره و آنرا ببندید. درون صفحه MainPage یک کنترل MediaPlayerElement قرار دهید (این کنترل از SDK 14393 به بعد قابل استفاده است!!) و یک دکمه که خاصیت Click را برای آن تعریف کرده باشید اضافه کنید: <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Button x:Name="btnPlay" Content="Play" Click="btnPlay_Clicked" /> <MediaPlayerElement x:Name="mediaPlayer" Grid.Row="1" AreTransportControlsEnabled="True" AutoPlay="False" /> </Grid> اکنون صفحه کدنویسی سی شارپ MainPage رو باز کنید و فضای نامی زیر رو به قسمت فضاهای نامی اضافه کنید: using Windows.Media.Playback; بالای کُنستراکتور (public MainPage...) این کد رو بنویسید: public MediaPlayer Player => PlaybackService.Instance.Player; حالا درون کُنستراکتور رویداد loadedـه صفحه را ایجاد نمایید: public MainPage() { InitializeComponent(); Loaded += MainPage_Loaded; } تابع آن: private void MainPage_Loaded(object sender, RoutedEventArgs e) { mediaPlayer.SetMediaPlayer(Player); } اکنون درون تابع رویداد کلیک دکمه کدهای زیر را بنویسید: var item = new MediaPlaybackItem(MediaSource.CreateFromUri(new Uri("http://dl.songdl.xyz/sOng/Album/Saman.Jalili-Ch.Haale.Khoobie/Saman.Jalili_06-Raahat.Maro.mp3"))); Player.Source = item; دقیقا یادم نیست برای اینکه از اینا استفاده کنید چه فضاهای نامی ای نیاز هست که اضافه کنید. اگر دیدید که رنگ زیر کلمات قرمز شد موس را چند ثانیه روی آن نگه دارید ویژوال استودیو به شما یک لامپ نشان میدهد که چنانچه روی آن کلیک کنید، یک لیست نشان خواهد داد که کزینه اول را در این لیست انتخاب کنید تا فضای نامی به صفحه اضافه شود. خب تمام شد ! پروژه را اجرا کرده و آنرا امتحان نمایید. نکات اضافی: برای نمایش آهنگ در SMTC نیاز هست که مقدار SMTCـه MediaPlayer را از آن گرفته و آنرا بروز رسانی نمایید.(از اینجا به بعد کپی شده از سورناست!) برای اینکار کافی است که شما در بالای کنستراکتور کد زیر را بنویسید: public SystemMediaTransportControls smtc = null; سپس درون Loaded کد زیر را بعد از کدی که در بالا نوشتید، درون try..catch بنویسید: try { smtc = Player.SystemMediaTransportControls; } catch {} با این کار SMTC پلیر را میگیریم. حال تابع زیر را جهت بروز رسانی کردن SMTC بنویسید public void UpdateSMTC(string singer, string title, string cover) { if (smtc == null) return; smtc.PlaybackStatus = MediaPlaybackStatus.Playing; smtc.DisplayUpdater.Type = MediaPlaybackType.Music; smtc.DisplayUpdater.MusicProperties.AlbumTitle = smtc.DisplayUpdater.MusicProperties.Title = title; smtc.DisplayUpdater.MusicProperties.AlbumArtist = smtc.DisplayUpdater.MusicProperties.Artist = singer; if (!string.IsNullOrEmpty(cover)) smtc.DisplayUpdater.Thumbnail = RandomAccessStreamReference.CreateFromUri(new System.Uri(cover)); smtc.DisplayUpdater.Update(); } حال درون رویداد کلیک بعد از کد پلی کردن، برای بروز رسانی آهنگ کافیست اینگونه عمل نمایید: UpdateSMTC("Saman Jalili", "Rahat Maro", "http://dl.songdl.xyz/sOng/Album/Saman.Jalili-Ch.Haale.Khoobie/Saman.Jalili-Che.Haale.Khoobie.jpg"); به همین سادگی! موفق باشید. منبع هم که همیشه وین نویس هست!
  6. 6 پسند
    برنامه همراه شهر به با قابلیت نصب بر روی ویندوز 10 و ویندوز 8.1 در دسترس عموم قرار خواهد گرفت قابلیت های این نسخه علاوه بر موارد موجود در همراه شهر نسخه موبایل موارد زیر می باشد: سپرده: انتقال وجه دسته‌ای سپرده انتقال وجه سپرده مستمر انتقال وجه دسته‌ای پایا انتقال وجه پایا مستمر گزارش پرداخت مستمر کارت: پرداخت دسته‌ای قبض
  7. 6 پسند
    آموزش برنامه نویسی با Xamain.Forms قسمت سوم : ساخت اولین پروژه (ماشین حساب) / ادامه در بخش قبلی با مقدمات آموزش ساخت پروژه و تصحیح پروژه (در صورت لزوم) آشنا شدیم . در این قسمت به آموزش ساخت اولین پروژه با زمارین میپردازیم . در فایل ویوی اصلی خود ابتدا رابط کاربری برنامه را طراحی میکنیم . طراحی رابط کاربری به شدت شبیه به WPF, UWP میباشد . در پروژه اول با آبجکت های نام آشنای Button و Grid کار میکنیم که همانطور که میدانید Grid فضایی جهت نمایش سایر آبجکت ها درون خود را به شما میدهد . Button یا دکمه ها برای گرفتن ورودی کاربر و انجام دستورات مرتبط استفاده میشود . آبجکت دیگری که در این پروژه به آن جهت نمایش نتیجه نیازمندیم Label میباشد که جهت نمایش متن غیر قابل ویرایش (متون ثابت مانند توضیحات) استفاده میکنیم . ابتدا یک کد XAML بسیار ساده ایجاد مینمائیم . سپس در قسمت XAML.CS کد های مربوط به کلیک دکمه ها را مینویسیم . حال به کمک شبیه ساز ها یا استفاده از دیوایس فیزیکی برنامه را اجرا کنید خواهید دید که برنامه بدون هیچ مشکلی دستگاه یا شبیه ساز اجرا میشود. در پایین اسکرین شاتی از اجرای برنامه در اندروید و ویندوز مشاهده میکنید . همانطور که مشاهده میکنید هر دو برنامه کاملاً مشابه همدیگر البته با قدری تفاوت در جزئیات اجرا گردیدند که این تفاوت های جزئی مربوط به طراحی Native سیستم عامل میباشد و زمارین به صورت پیشفرض از استایل های پیشفرض استفاده میکند تا برنامه بیشتر شبیه به اپ های مرسوم در سیستم عامل شوند . کد های انتشار یافته در بالا نیز نیاز به توضیحات زیادی ندارد به جز اینکه در قسمت XAML از HorizontalTextAlignment و VerticalTextAlignment استفاده شده که بر خلاف اکثر زبان های رایج از ککلمات Start, Center و End استفاده شده . لازم به توضیح است که VerticalTextAlignment معین محل قرار گیری متن در جهت عمودی در صفحه (یا بهتر بگم آبجکت پدر) را تعیین میکند که استارت یعنی در نقطه شروع آبجکت پدر (بالای آن) قرار میگیرد ، یا سنتر در مرکز و End در انتها یا پایین آبجکت . همچنین HorizontalTextAlignment به طور مشابه همین کار را در جهت افق انجام میدهد و استارت آن به معنی سمت چپ آبجکت و End آن به معنای راست آبجکت میباشد . از دیگر موارد قابل ذکر این است که FontSize در زمارین به صورت هم عددی و هم به صورت Large , small , Medium و.... قابل استفاده است و هر دوی آن ها صحیح است ، جهت Bold کردن یا Italic کردن متن نیز میتوانید از FontAttributes استفاده نمائید که البته تنها به بولد و ایتالیک محدود است و گزینه هایی مانند SemiBold را شامل نمیشود ! دانلود سورس کد
  8. 5 پسند
    شروع برنامه نویسی برای گوشی های آیفون روش های مختلفی دارد، که یکی از آنها استفاده از زامارین و زبان سی شارپ است. این روش هم مانند روش های دیگر دردسر های خود را برای شروع دارد مخصوصا برای افرادی که سیستم مک (مک بوک یا ...) ندارند. در این آموزش سعی شده سریع ترین و بهترین روش برای شروع کار به شما یاد داده شود. چگونه macOS Sierra 10.12 را بر روی VirtualBox نصب کنیم ؟ در # مرحله اول VirtualBox را از این لینک دریافت کرده و سپس به راحتی و با زدن چند دکمه بعدی نصب کنید. # مرحله دوم فایل ویرچوال باکس که شامل مک او اس آماده شده هست را دریافت کنید و در پوشه و درایوی که به اندازه کافی (بالای 50 گیگ) جا دارد استخراج (Extract) کنید. #مرحله سوم یک ماشین مجازی جدید ایجاد کنید: (با تنظیمات زیر) تنظیم نام، نوع و ورژن مطابق شکل تنظیم 4 گیگ رم در مرحله بعدی انتخاب ماشین مجازی موجود و سپس انتخاب فایل استخراج شده در مرحله قبل تغییر تنظیمات در بخش سیستم > مادربورد، غیر فعال کردن فلاپی و تنظیم چیپست ICH9 مطابق شکل انتخاب 2 هسته فعال تنظیم 128 مگ رم گرافیک تنظیم آداپتور نتورک مطابق شکل #مرحله پنجم کد ها ویرچوال را وارد CMD کنید. CMD را در حالت administrator اجرا کنید و کد های موجود در فایل زیپ را دونه به دونه در کامند پیست کرده و اینتر را بزنید. # مرحله ششم اجرای ماشین مجازی قبل از اجرای ماشین مجازی به این نکته دقت کنید که hyper-v در سیستم شما روشن نباشد. در صورت اینکه به این سیستم نیاز دارید میتوانید با روش زیر این کار را انجام دهید. < داشتن همزمان hyper-v و سیستم های موازی دیگر در یک کامپیوتر: برای این کار C:\>bcdedit /copy {current} /d "No Hyper-V" The entry was successfully copied to {ff-23-113-824e-5c5144ea}. C:\>bcdedit /set {ff-23-113-824e-5c5144ea} hypervisorlaunchtype off The operation completed successfully. را در CMD , Administator اجرا کنید. دقت کنید که کدی را که در مرحله اول میدهد را در مرحله دوم وارد کنید. در صورت ری استارت کردن کامپیوتر با این صفحه روبرو میشوید که می توانید هایپر وی را غیر فعال کنید. > ماشین مجازی رو اجرا کرده و منتظر بمانید که ستاپ مک نمایان شود. مطابق شکل های زیر ستاپ را کامل کنید. حالا نوبت به راه اندازی ابزار های برنامه نویسی میرسه. 1- نصب XCode : شما میتوانید ایکس کد را از این لینک یا استور دانلود و به راحتی نصب کنید. (ورژن 8 به بالا) 2- نصب ویژوال استادیو مک: visual studio 2017 mac که میتوانید از سایت خود مایکروسافت دریافت کنید و قسمت های مورد نیاز خود را نصب کنید. تصویر محیط برنامه نکات مهم : > توصیه میشود از ورژن های قبلی زامارین استفاده نکنید زیرا ورژن های آخر مک اجازه دسترسی به فایل های سیستم را نمیدهد و زامارین در موقع کامپایل به مشکل بر میخورد. >برای انتقال فایل بین ویندوز و مک، شیر ویندوز را فعال کرده و در سیستم عامل مک قسمت Finder > Go > Connect to server آی پی ویندوز را زده و به فایل های شیر دسترسی داشته باشید. با آرزوی موفقیت و تولید اپ های بیشتر و با کیفیت ایرانی.
  9. 5 پسند
    سلام، بصورت پیشفرض Encoding 1252 در باندل نهایی افزوده نمیشه. برای اینکار Propertiesـه پروژه رو باز کنید و به تب Android Options بروید. در این صفحه از تب Linker رو انتخاب کنید و گزینه Linking رو روی Sdk Assemblies Only رو انتخاب کنید. در قسمت Additional supported encodings هم گزینه west رو تیک بزنید. همین! موفق باشید.
  10. 5 پسند
    همراه شهر نسخه ویندوز موبایل بروزرسانی جدیدی دریافت کرد و امکانات جدیدی به آن افزوده شده است، به زودی نسخه دسکتاپ هم به آن اضافه خواهد شد. امکانات جدید این نسخه به شرح زیر می باشد: امکان به اشتراک‌‌ گذاری نتیحه تراکنش‌ها اضافه شدن انتخاب سپرده‌های شخصی در محاسبه شبا گزارش قبوض پرداخت‌شده گردش سپرده بر اساس تاریخ مکان تماس مستقیم با سامانه مردمی بانک شهر بهینه‌سازی و اصلاحات متنی نمایش محدودیت های انتقال وجه پایا ذخیره نام کاربری با انتخاب کاربر
  11. 5 پسند
    با سلام. امروز با معرفی و آموزش Windows Template Studio که به تازگی از سمت مایکروسافت منتشر شده است، در خدمت شما هستیم. ویندوز تمپلیت استودیو در حقیقت یک محیط در ویژوال استودیو است که شما پروژه ی خود + امکانات و شمای کلی پروژه را تعریف میکنید، و تمپلیت استودیو قسمت زیادی از نرم افزار را برایتان کد می زند! ویندوز تمپلیت استودیو یک جانشین تمام عیار برای App Studio است که هم برای مبتدیان و هم برای حرفه ای ها کاربردی است. حالا بریم سراغ اصل مطلب: به چه چیزی نیاز داریم؟ 1-ویندوز 10 2-ویژوال استودیو 2017 (روی 2015 تست نشده، امکان دارد به مشکلاتی بخورد) 3-آخرین نسخه از SDK ویندوز 10 تمپلیت استودیو را دانلود و نصب کنید! 1-از این لینک آخرین نسخه ی ویندوز تمپلیت استودیو را دانلود کنید. 2-فایل دانلود شده را اجرا کنید تا فایل های مربوطه را دانلود و نصب کند. امکان دارد که برای نصب به VPN نیاز داشته باشید. حجم دانلودی هم زیر 1 گیگابایت می باشد. شروع به کار با تمپلیت استودیو 1-ویژوال استودیو را باز کنید. قسمت File/new/project را بزنید. 2- در صورت نصب کامل و صحیح تمپلیت استودیو باید در قسمت C#/Universal Windows ، گزینه ی Windows Template Studio(Universal Windows) را ببینید. روی آن کلیک کنید تا صفحه ی تمپلیت استودیو باز شود. 3- در اینجا شما نوع پروژه و فریمورک خود را مشخص میکنید. -نوع پروژه: الف)Navigation Pane شما یک پروژه به نوع نویگیشن پین خواهید داشت که نویگیشن بین صفحات مختلف با کمک همبرگر منو صورت می گیرد. ب)Blank تمپلیت استودیو به شما یک پیج خالی تحول خواهد داد. هر جور که خود صلاح میدانید نویگیشن آن را درست کنید ج)Pivot and tabs یک پیج حاوی چند تب به شما داده می شود که نویگیشن به کمک پیوت (Pivot) انجام خواهد شد. -فریموک استفاده شده(معماری نرم افزار): الف) Code Behind کد نویسی منطقی شما داخل کد بیهایند انجام خواهد شد. ب)MVVM Light کد نویسی با معماری MVVM انجام خواهد شد و از فریمورک سوم شخص MVVM Light استفاده خواهد شد. ج)MVVM Basic کد نویسی به صورت MVVM انجام می شود اما به صورت ساده. از هیچ گونه فریمورکی هم استفاده نخواهد شد. بعد از انتخاب فریمورک و نوع نویگیشن، Next را بزنید. 4- انتخاب ویژگی ها و امکانات برنامه الف) پیج ها در می توانید پیج های مختلفی را به نرم افزار خود اضافه کنید. انواع این پیج ها : ساده، همراه با چارت، همراه با گرید ویو، همراه با نقشه، پیج مستر دیتیل (همانند نرم افزار میل، تلگرام دسکتاپ، یونیگرام و ...)، همراه با مدیا پلیر، پیج تنظیمات، پیج تب دار (همراه با پیوت) و وب ویو هستند. ب) امکانات در اینجا می توانید امکانات مختلفی را به نرم افزار خود اضافه کنید. -مدیریت لایف سایکل نرم افزار شامل: مدیریت ذخیره ی ستینگز، مدیریت ساسپند و ادامه ی نرم افزار -بک گراند تسک -ارتباط به کاربر شامل : توست نوتیفیکیشن، پوش نوتیفیکیشن از طریق داشبورد، کاشی زنده و پوش نوتیفیکیشن آژور. امکانات نرم افزار خود را انتخاب کنید، Create را بزنید و صبر کنید تا تمپلیت استودیو نرم افزار را برایتان کد بزند مشاهده می شود که تمپلیت استودیو بسیار کد تمیز و قابل فهمی را جنریت میکند. که به راحتی قابل شخصی سازی و ادامه ی روند توسعه ی نرم افزار است. در ادامه نرم افزار را اجرا می کنیم به خوبی کار میکند ویندوز تمپلیت استودیو یک پروژه ی متن باز است که می توانید در گیت هاب پیدایش کنید.
  12. 5 پسند
    با سلام، یه سری نکات هست که بطور تجربی بدست آوردم و میتونه تو جلوگیری از خطا ها و دولوپ سریع تر کمکتون کنه. >> بعد از راه اندازی محیط برنامه و نصب sdk و ndk و jdk که مورد نیازه برای اندروید در زامارین سعی کنید ارتباط با اینترنت را همراه با وی پی ان داشته باشید، چون ممکنه سیستم به یک سری فایل نیاز پیدا کنه که باید از گوگل دانلود کنه که متاسفانه ایران تحریم هست ولی درصورت نداشتن وی پی ان می شود این فایل هارو بصورت دستی اضافه کرد. دقت داشته باشید که ورژن نوگت ها یا کامپوننت های Support گوگل باید مطابق با ورژنی که پروژه را برای آن اندروید کامپایل میگیرد باشد، نه جدیدترین آن. وقتی ورژن هدف کامپایل پروژه رو مثلا 6 در نظر میگیرید اصلا نگران اجرا شدنش روی ورژن های پایین تر در قدم نخست نباشید (4.1) و ابزار ها و دسترسی های مخصوص برای این موضوع مهم است. هیچ وقت مانند ویندوز یونیورسال تنظیمات خروجی برنامه رو بدون اطلاعات کامل تغییر ندهید، ممکن است باعث مشکل در آینده شود. نسخه دیباگ در حالت پیشفرض روی دیوایس واقعی کار نمیکند و نسخه ریلیسیس هم بر عکس. طبق عادت مانند برنامه نویسی ویندوز برای سبک شدن یا برطرف شدن ارور ها فولدر object و bin را پاک نکنید.
  13. 4 پسند
    با سلام. امیدوارم تا اینجای آموزش سخت نبوده باشه . در این قسمت با Command آشنا میشیم . کامند ها همون ایونت ها هستن که به جای اینکه توی کد بیهایند (فایل xaml.cs) بنویسیم توی مدل ویو مینویسین . ابتدا یک کلاس با نام AppCommand در روت پروژه بسازید و این کد را داخل ان کپی کنید . using System; using System.Windows.Input; public class AppCommand : ICommand { #pragma warning disable CS0067 // The event 'AppCommand.CanExecuteChanged' is never used public event EventHandler CanExecuteChanged; #pragma warning restore CS0067 // The event 'AppCommand.CanExecuteChanged' is never used public static AppCommand GetInstance() { return new AppCommand() { CanExecuteFunc = obj => true }; } public Predicate<object> CanExecuteFunc { get; set; } public Action<object> ExecuteFunc { get; set; } public bool CanExecute(object parameter) { return CanExecuteFunc(parameter); } public void Execute(object parameter) { ExecuteFunc(parameter); } } برای استفاده از این کلاس در صفحه MainView یک باتن اضافه میکنیم . کد نهایی صفحه به صورت زیر خواهد بود: <Page.DataContext> <VM:MainViewVM/> </Page.DataContext> <Grid Background="{Binding ColorName}"> <Grid VerticalAlignment="Center" HorizontalAlignment="Center"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <TextBox Grid.Row="0" Text="{Binding ColorName, Mode=TwoWay}" BorderThickness="2" VerticalAlignment="Center" HorizontalAlignment="Center" Width="200"/> <Button Grid.Row="1" Content="About" Command="{Binding AboutCmd}" Margin="0,5" Width="120" HorizontalAlignment="Center"/> </Grid> </Grid> خب حالا توی ویو مدل باید کامند رو تعریف کنیم public AppCommand AboutCmd { get; set; } نکته خیلی مهم : تمام پراپرتی ها و کامند ها و.... ای که قراره از طریق زمل بتونیم بایندشون کنیم باید حتما و حتما به صورت property تعریف شده باشن یعنیpublic type PropertyName{get;set;} در غیر اینصورت بایندینگ انجام نمیشه مثلا اگه نوشته باشید public type pname; حالا کانستراکتور مربوط به ویو مدل خودمون رو میسازم و کد های زیر را داخلش مینویسیم : public MainViewVM() { AboutCmd = AppCommand.GetInstance(); AboutCmd.ExecuteFunc = ShowAbout; } بدون کوچک ترین شکی به خاطر اینکه هنوزShowAbout را تعریف نکردیم ازش ارور میگیره . پس ماوس رو روی ارورش ببرید و از پیشنهادات ویژوال استدیو گزینه اول یعنی Generate method 'MainViewVM.ShowAbout' را انتخاب کنید . حال تابعی به صورت زیر برای شما ایجاد میشود. private void ShowAbout(object obj) { throw new NotImplementedException(); } تابع را به صورت زیر تغییر میدهیم . private async void ShowAbout(object obj) { await new MessageDialog("I am learning MVVM").ShowAsync(); } حال برنامه را اجرا کنید . پس از اجرا روی کلید about کلیک کنید خواهید دید که پیام شما نمایش داده خواهد شد .
  14. 4 پسند
    بسم الله الرحمن الرحیم سلام؛ به درخواست دوستان، یه سیستم زنگ هوشمند مدرسه قرار هست بسازیم. البته تو هوشمند بودنش شک دارم ولی خب از اونجا که هر کسی به هر چیزی که یه چیپ داشته باشه بهش عبارت #هوشمند می چسبونه، منم تصمیم گرفتم بهش بگم هوشمند. خب بریم سراغ لوازم مورد نیاز، نکته اینکه لازم نیست عینا همین ها رو بخرید، می توانید از مدل های مشابه هم استفاده کنید. اگر در خرید و انتخاب شک دارید، همینجا بپرسید! مواد لازم: 1. یک برد آردوئینو. من برای این کار UNO رو پیشنهاد میدم! چون به راحتی هم پروگرام میشه، تازه قیمتش هم خیلی کمه و برای کار ما هم کافیه! 2. ماژول ساعت فوق دقیق DS3231، یه ماژول قدرتمند و کم مصرف با قیمت ارزان! تا سال 2100 برنامه ریزی شده و علاوه بر ساعت، تاریخ رو هم داره که البته مورد نیاز ما نیست! از همه مهم تر یک باتری ساعت هم داره که در صورتی که برق قطع شد، زمان بندی ما به فنا نره . اگرچه تاریخش شاید برای مدارس مهم باشه تا در ایام تعطیل زنگ کار نکنه! ولی خب کلا از برق بکشیمش بیرون بهتره. 3. ماژول رله Relay Module: این رو برای مدیریت برق نیاز داریم! یدونه تک کاناله بخرید! خرج الکی هم نکنید! 4. مقداری سیم مناسب با ولتاژ 220 ولت و 5 ولت و همچنین به یک زنگ مدرسه هم نیاز داریم! حالا بریم سراغ وصل کردن این لوازم! توی UNO ما پایه SDA ماژول رو به پایه A4 و پایه SLC رو به پایه A5 آردوئینو وصل کردیم. VCC رو هم به 3.5 ولت و GND هم که تکلیفش مشخصه! من برای روشن کردن زنگ از پایه 6 دیجیتال استفاده کردم که به دلخواه خودتون می تونید از پایه دیجیتال دیگری هم استفاده کنید! یه سیم به پایه 6 وصل می کنید. این پایه در اصل رله رو کنترل می کنه، این پایه رو باید به پایه in رله متصل کنید. VCC و GND رله رو هم به پایه های مربوطه روی آردوئینو متصل کنید. در آخر کابل برق رو به رله وصل کنید. (سیم نول مستقیم به زنگ متصل می شه، رله رو سر راه سیم فاز قرار بدید تا مدار رو قطع و وصل کنه!). پایان! سعی کنید کار رو تمیز انجام بدید و قبل از لحیم کاری از بردبورد استفاده کنید تا صحت اتصالات رو بسنجید. اگر هم لحیم کاری بلد یستید، قبل از اینکه خودتون و وسایل رو بسوزونید برید به یه تعمیرکار لوازم الکترونیک رجوع کنید و جان خودتون رو نجات بدید! بگذریم! حالا نوبت برنامه نویسی هست. من برای این زنگ مدرسه اینترفیس خاصی در نظر نگرفتم و همونطور که گفتم موقع کامپایل دیگه زمان ها رو مشخص می کنیم! البته اگر می خواید از طریق راه دور و با بلوتوث زنگ ها رو کنترل کنید هم بگید تا انجامش بدیم ولی خب فکر کنم لازم نیست اصلا، چون زنگهای مدرسه ثابته و تغییر ندارند! 1. کابل USB رو به برد متصل کنید. 2. این کتابخونه رو دانلود کنید و در IDE آردوئینو اضافه و سپس به پروژه بیافزایید! 3. کدهای زیر رو وارد محیط برنامه نویسی کرده و آپلود کنید روی برد! //این همون کتابخونه است که دانلود کردیم! #include <DS3231.h> //این کتابخونه رو دستی اضافه کنید (بنویسیدش!) #include <Wire.h> //یک شی از RTCDateTime میسازیم تا زمان رو در اون ذخیره کنیم //و به جزییاتش دست پیدا کنیم RTCDateTime dt; // یک ساعت از کتابخونه مورد نظر می سازیم DS3231 clock; void setup() { // put your setup code here, to run once: Serial.begin(9600); // شروع به کار ماژول رو اعلام می کنیم Serial.println ("Initialize DS3231"); //ساعت شروع به کار می کند: clock.begin (); //زمان رو از کامپیوتر دریافت و تنظیم می کنیم: clock.setDateTime (__DATE__, __TIME__); //پایه 6 رو به عنوان پایه خروجی تنظیم می کنیم pinMode (6, OUTPUT); } void loop() { // put your main code here, to run repeatedly: // مقدار زمان رو در متغیر میریزیم و سپس چاپ می کنیم: dt = clock.getDateTime (); Serial.print ("Raw Time: "); Serial.print (dt.hour); Serial.print (":"); Serial.print (dt.minute); Serial.print (":"); Serial.print (dt.second); Serial.println (""); //یک تاخیر 1 ثانیه ای برای هر بار چاپ لحاظ می کینم: delay(1000); //یک شرط قرار دادیم که اگر ساعت 13 و دقیقه 23 و ثانیه کمتر از 5 // بود پایه 6 رو فعال کنه. if ( (dt.hour == 13) && (dt.minute == 23) && (dt.second < 5) ) { digitalWrite(6, HIGH); } else { //اگر هم نبود، عیر فعال کنه! digitalWrite(6, LOW); } } نکته: برای اینکه بتونید خروجی رو ببینید، CTRL + Shift + M رو بزنید! سعی کردم مستند نویسی کنم تا هم با کدها آشنا بشید و هم اینکه بتونید تغییرات دلخواه رو بدید، اگر سوالی بود در خدمتم! فایل پروژه رو هم در انتها می تونید دانلود کنید. school.ino
  15. 4 پسند
    سلام، توی تاپیک قبلی > آموزش ساخت دستیار صوتی و تشخیص گفتار صوتی رو آموزش داده بودم. اما اگه از این کد استفاده کرده باشید می دونید که در بعضی موارد جواب رو نمیده و به احتمال زیاد ف-ی=ل=ت-ر هست. خب برای رفع این مشکل من یه api کوچیک آماده کردم که شما کافیه که فایلی که رکورد کردید رو به این آدرس پست کنید: http://appsoorena.ir/api/wit نمونه کد برای ارسال: async Task<string> GetAsync(StorageFile file) { try { using (HttpClient httpClient = new HttpClient()) { MultipartFormDataContent form = new MultipartFormDataContent(); using (Stream fileStream = (await file.OpenAsync(FileAccessMode.ReadWrite)).AsStream()) { byte[] bytes = ReadStream(fileStream); form.Add(new ByteArrayContent(bytes, 0, bytes.Length), "file", file.Name); HttpResponseMessage response = await httpClient.PostAsync("http://appsoorena.ir/api/wit", form); response.EnsureSuccessStatusCode(); httpClient.Dispose(); string result = response.Content.ReadAsStringAsync().Result; return result; } } } catch (Exception ex) { Debug.WriteLine("Ex: " + ex.Message + "\r\n\r\n" + ex.Source + "\r\n\r\n" + ex.StackTrace); } return ""; } به صورت پیشفرض این میاد از AccessToken من استفاده میکنه و ارسال فایل به ویت رو انجام میده، اگه مایل هستید که از AccessToken خودتون استفاده کنید، کافیه که توی هدر ارسالی نام هدر رو Authorization بذارید و مقدار اون رو برابر با AccessToken خودتون قرار بدید: مثال: httpClient.DefaultRequestHeaders.Add("Authorization", "ACCESS TOKEN E SHOMA"); نکته: این API قابلیت ارسال همزمان چندین فایل رو داره: async Task<string> GetAsync(IReadOnlyList<StorageFile> files) { try { using (HttpClient httpClient = new HttpClient()) { //httpClient.DefaultRequestHeaders.Add("Authorization", "ACCESS TOKEN E SHOMA"); MultipartFormDataContent form = new MultipartFormDataContent(); Dictionary<string, byte[]> dic = new Dictionary<string, byte[]>(); foreach (StorageFile f in files) { using (Stream fileStream = (await f.OpenAsync(FileAccessMode.ReadWrite)).AsStream()) { byte[] bytes = ReadStream(fileStream); string name = f.Name; dic.Add(name, bytes); } } foreach (var f in dic) form.Add(new ByteArrayContent(f.Value, 0, f.Value.Length), "file", f.Key); HttpResponseMessage response = await httpClient.PostAsync("http://appsoorena.ir/api/wit", form); response.EnsureSuccessStatusCode(); httpClient.Dispose(); string result = response.Content.ReadAsStringAsync().Result; return result; } } catch (Exception ex) { Debug.WriteLine("Ex: " + ex.Message + "\r\n\r\n" + ex.Source + "\r\n\r\n" + ex.StackTrace); } return ""; } جواب به صورت لیستی از کلاس WitResponseObject خواهد بود. در اینجا من 8 فایل ارسال کردم که اینم جوابش: [ { "msg_id": "0XuSI5fNDdIXwvg2w", "_text": "برای", "entities": { "intent": [ { "confidence": 1, "value": "کاری " } ] } }, { "msg_id": "0jur6vqRHwR5iULOx", "_text": "دانلود", "entities": { "intent": [ { "confidence": 1, "value": "کاری " } ] } }, { "msg_id": "0bjs6UfOFV5RWxlA6", "_text": "این", "entities": { "intent": [ { "confidence": 1, "value": "کاری " } ] } }, { "msg_id": "0sPszLjV7Emx81ZFo", "_text": "کد", "entities": { "intent": [ { "confidence": 1, "value": "کاری " } ] } }, { "msg_id": "0VUVcyH4DwD3O2rqH", "_text": "زیر", "entities": { "intent": [ { "confidence": 1, "value": "کاری " } ] } }, { "msg_id": "0EqbLSnVxjoIZa3rs", "_text": "راه", "entities": { "intent": [ { "confidence": 1, "value": "کاری " } ] } }, { "msg_id": "0amyxK8K5g1bCqBep", "_text": "اسکن", "entities": { "intent": [ { "confidence": 1, "value": "کاری " } ] } }, { "msg_id": "0Joftm7K5HpGOyNFB", "_text": "کنید", "entities": { "intent": [ { "confidence": 1, "value": "کاری " } ] } } ] موفق باشید. منبع: وین نویس
  16. 4 پسند
    سلام؛ برد Uno یکی از محبوب ترین بردهایی است که تولید شده و البته همانطور که از نامش پیداست (UNO در ایتالیایی یعنی عدد یک) آغازگر انقلاب آردوئینو بوده است. بردی ارزان (حدود 20 هزار تومان) که بر پایه mega328 توسعه یافته و بر همین اساس امکانات خوبی را برای ما فراهم می کند: 14 پین برای ورود و خروج اطلاعات که 6 تا از آنها به عنوان pwm نیز قابل استفاده هستند یک مزیت برای هر کاربری است که تعداد زیادی ورودی و خروجی در مدار خود دارد. وجود پورت USB از نوع مینی علاوه بر آسان کردن پروگرام این برد، تغذیه آن را هم از طریق طیف وسیعی از منبع تغذیه های موجود در بازار (شارژر موبایل!) امکان پذیر کرده است. البته جک مادگی ضخیم شارژ همچنان بر روی این برد قابل مشاهده است، تا در صورت نیاز به درگاه USB بتوانید همچنان برد را تغذیه کنید. پین هدرISCP و کلید ریسیت هم از سایر چیزهایی است که در این برد وجود دارد. برای راه اندازی این برد به صورت پایدار به اختلاف پتانسیل مابین 6 تا 20 ولت نیاز دارید، البته اگر ولتاژ را به بیش از 12 ولت برسانید، به علت افزایش دمای چیپ بهتر است از یک سینک یا خنک کننده دیگر استفاده کنید. بهتر است بگوییم بهترین بازه عملیاتی این برد در ولتاژ 7 تا 12 ولت قرار دارد. حافظه این برد 32 کیلوبایت هست که کاملا کافی به نظر می رسد! 2 کیلوبایت SRAM و 1 کیلو بایت EEPROM هم در اختیار شماست (البته من نمی دونم دقیقا کاربردشون چیه!). در آخر هم خوب است بدانید که با دو پین RX و TX می توانید از ماژول های رادیویی مثل بلوتوث هم استفاده کنید!
  17. 4 پسند
    سلام؛ احتمالا برای شما هم این سوال پیش آمده باشد که چه زمانی باید از بردهای رسپبری پای و چه زمانی از بردهای (یا ماژول‌های) آردوئینو استفاده کرد. با این که این یک قانون نیست اما در کلیت می‌تواند راهگشا باشد. هر گاه نیاز بر این باشد که شما اطلاعاتی را از محیط دریافت کنید یا کاری بر روی سیستم انجام دهید، بهتر است از بردهای آردوئینو و ماژول‌های آن استفاده کنید. و هر گاه نیاز به پردازش این اطلاعات دارید یا می‌خواهید دستورات پیچیده‌ای برای اعمال به بردهای آردوئینو بدهید، باید از رسپبری پای یا سایر بردهای دارای سیستم عامل استفاده کنید. البته واضح هست که برد رسپبری پای خود می‌تواند به وسیله سنسور، برخی از اطلاعات را دریافت کند، اما ماژول‌های موجود برای بردهای آردوئینو بسیار گسترده تر و ارزانتر هستند. همچنین باید به این نکته هم توجه کرد که گوشی موبایل هم می‌تواند تبدیل به واحد پردازشی سیستم ما شود. پس با رسپبری پای تمام اطلاعات را از آردوئینو دریافت و پردازش کنید.
  18. 4 پسند
    آموزش کار با Navigationbar در Xamarin.Forms همانطور که در آموزش قدم به قدم برنامه نویسی Xamarin.Forms نیز اشاره کردم یکی از انواع صفحات موجود در زمارین فرم NavigationPage میباشد . به صورت پیشفرض این صفحه در بالای هر صفحه یک کادر حاوی عنوان صفحه و کلید بازگشت به صفحه قبل نشان میدهد . در این آموزش خواهیم آموخت چطور این صفات را تغییر دهیم . 1 - پنهان کردن کامل نوار بالا در یک صفحه : در صفحه مورد نظر خود کد زیر را جهت عدم نمایش NavigationBar وارد کنید : NavigationPage.SetHasNavigationBar(this, false); و جهت نمایش مجدد آن از کد زیر استفاده کنید : NavigationPage.SetHasNavigationBar(this, true); 2 - جهت عدم نمایش کلید بازگشت در NavigationPage : NavigationPage.SetHasBackButton(this, false); جهت نمایش مجدد : NavigationPage.SetHasBackButton(this, true); نکته : اگر صفحه ای صفحه نخست باشد true کردن نمایش کلید بازگشت باعث نمایش این کلید نخواهد شد . نکته : اگر صفحه ای کلید بازگشت از آن محو شود باعث از کار افتادن عملکرد کلید بازگشت دستگاه های اندروید و ویندوز فون نخواهد شد .
  19. 4 پسند
    آموزش برنامه نویسی با Xamain.Forms قسمت هفتم: کار با لیست ویو لیست ویو Incremental Loading در این قسمت آموزش قصد دارم به شما نشون بدم که چطور میتونید یک لیست بسازید که به صورت خودکار آیتم های بیشتری لود کنه . این نوع لیست ویو چه کاربردی داره و چه زمانی از اون استفاده میکنیم ؟ این نوع لیست برای زمان هایی کاربرد داره که لیست ما احتمالا طولانی شدن اون زیاد هست یا حجم داده ها به هر نحوی زیاد هست یا اصلا اطلاعاتی که از سرور دریافت میکنیم به صورت صفحه به صفحه است و در هر صفحه به عنوان مثال 10 یا 20 آیتم جدید به ما برگردونده میشه . در اینجا من یک برنامه ساده میسازم که فقط یک متن ساده همراه با عکس دریافت میکند و به کاربر نشان میدهد . ابتدا یک لیست ویو میسازیم . برای سادگی کار از ItemTemplate برای استایل دادن به آیتم های درون لیست استفاده میکنیم . <ListView x:Name="Lst" > <ListView.ItemTemplate> <DataTemplate> <ViewCell> <Grid BackgroundColor="LightCyan"> <Grid.ColumnDefinitions> <ColumnDefinition Width="87"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Grid Grid.Column="0"> <Image Grid.Column="0" Margin="0,7.5" HeightRequest="70" WidthRequest="70" Source="{Binding Img}" Aspect="AspectFit" VerticalOptions="Fill" HorizontalOptions="Fill" /> </Grid> <StackLayout Grid.Column="1" VerticalOptions="Center"> <Label Text="{Binding Text1}" FontAttributes="Bold" /> <Label Text="{Binding Text2}" TextColor="#FF646464" FontAttributes="Italic" /> <Label Text="{Binding Text3}" TextColor="#FF646464" Margin="0,0,10,0" FontAttributes="Bold"/> </StackLayout> </Grid> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> همونطور که مشاهده میکنید لیست ویو یک لیست کاملاً ساده هست و همونطوری ساخته شده که توی برنامه نویسی UWP و WPF هم لیست ویو میسازیم با این تفاوت که داخل DataTemplate یک ViewCell هم باید بگزاریم . کار ما سمت XAML تموم شده حالا میریم داخل کد های سی شارپ . حال یک کلاس برای بایند کردن Template به لیست میسازیم به صورت زیر : public class OurLstItems { public string Img { get; set; } public string Text1 { get; set; } public string Text2 { get; set; } public string Text3 { get; set; } } حال یک ObservableCollection از همین کلاس میسازیم . یکی از خاصیت های اصلی ObservableCollection این هست که در صورت اضافه و کم شدن آیتم به صورت خودکار UI نیز آپدیت میشود پس برای راحتی از همین نوع کالکشن استفاده میکنیم و آنرا به صورت یک متغیر سراسری در پیج معرفی میکنیم . ObservableCollection<OurLstItems> items = new ObservableCollection<OurLstItems>(); همچنین جهت عکس یک عکس نمونه کوچک را انتخاب کردم که به شکل سراسری در پروژه تعریف مینماییم . const string image = "http://files.softicons.com/download/system-icons/othoni-afis-icons-by-steven-zangh/png/60x60/Settings.png"; استراتژی جهت لود آیتم های جدید ! برای لود کردن آیتم های جدید لیست باید یک استراتژی در نظر بگیریم که چه زمانی باید ایتم های جدید را لود کنیم . در صورتیکه اطلاعات از اینترنت دریافت میشوند و همانطور که میدانید ممکن است سرعت اینترنت خصوصاً در ایران در بسیاری مواقع پایین باشد لذا لازم است سریع تر این کار را انجام دهیم و گاهی که به عنوان مثال از حافظه دستگاه اطلاعات استخراج میشود با رسیدن به انتهای لیست نیز میتوان این کار را کرد ! به عنوان یک استاندارد من در کد خودم در هر صفحه 20 آیتم جدید تولید میکنم و به برنامه تحویل میدهم (که در سایت های خبری ، موزیک و .... نیز معمولا تعداد آیتم ها 10 ، 15 یا 20 مورد در نظر گرفته میشوند.) private List<OurLstItems> GenerateNewItems() { return new List<OurLstItems>() { new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, }; } حال در Constructor برنامه کالکشن خود را به لیست ویو بایند میکنیم Lst.ItemsSource = items; در لیست ویو های زمارین دو Event به نام های ItemAppearing و ItemDisappearing از این دو تا ایونت جهت فهمیدن اینکه چه آیتمی در حال محو شدن از دید کاربر هستند یا بلعکس چه آیتم هایی در حال اضافه شدن به ویوی برنامه میباشند . تفاوت این دو ایونت در این است که یکی به ابتدای صفحه اشاره دارد و دیگری به انتهای صفحه . اگر میخواهید استراتژی لود آیتم ها به صوتی باشد که در صورت نزدیک شدن به آیتم های پایانی لیست ایتم های جدید لود شود بهتر است از ItemAppearing استفاده نمائیم . همچنین استفاده همزمان از هر دو ایونت میتواند به ما نشان دهد که در گوشی کاربر به صورت همزمان چند آیتم به نمایش در می آید . من در اینجا از ItemAppearing استفاده میکنم و استراتژی به این صورت خواهد بود که 15 آیتم به پایان لیست آیتم های جدید لود خواهم کرد . private void Lst_ItemAppearing(object sender, ItemVisibilityEventArgs e) { var item = e.Item as OurLstItems; var index = items.IndexOf(item); if(items.Count - index <= 15) foreach (var IOA in GenerateNewItems()) { items.Add(IOA); } } کار تمام است فقط به این دلیل که در ابتدای اجرای برنامه آیتمی در لیست وجود ندارد لذا در حین اجرای برنامه هم این سه خط را مینویسیم تا برنامه به درستی کار کند . foreach (var item in GenerateNewItems()) { items.Add(item); } به این ترتیب کد نهایی برنامه ما به صورت زیر خواهد بود : public partial class MainPage : ContentPage { public class OurLstItems { public string Img { get; set; } public string Text1 { get; set; } public string Text2 { get; set; } public string Text3 { get; set; } } const string image = "http://files.softicons.com/download/system-icons/othoni-afis-icons-by-steven-zangh/png/60x60/Settings.png"; ObservableCollection<OurLstItems> items = new ObservableCollection<OurLstItems>(); public MainPage() { InitializeComponent(); Lst.ItemsSource = items; foreach (var item in GenerateNewItems()) { items.Add(item); } } private List<OurLstItems> GenerateNewItems() { return new List<OurLstItems>() { new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, new OurLstItems(){ Img = image, Text1 = $"First{new Random().Next()}", Text2 = $"Second{new Random().Next()}",Text3 = $"Third{new Random().Next()}"}, }; } private void Lst_ItemAppearing(object sender, ItemVisibilityEventArgs e) { var item = e.Item as OurLstItems; var index = items.IndexOf(item); if(items.Count - index <= 15) foreach (var IOA in GenerateNewItems()) { items.Add(IOA); } } } خروجی کار : اگر در تصویر فوق دقیق شوید متوجه خواهید شد که با نسخه UWP تفاوت فراوانی دارد هم آیکن ها کوچک تر هستند و هم خط سوم Text3 نمایش داده نمیشود ! برای حل این مشکل تنها کافیست در کد های XAML یک مشخصه به لیست ویو اضافه نمائید . HasUnevenRows یعنی کد زمل به صورت زیر تغییر خواهد کرد . <ListView x:Name="Lst" ItemAppearing="Lst_ItemAppearing" HasUnevenRows="True"> ..... </ListView>
  20. 4 پسند
    آموزش برنامه نویسی با Xamain.Forms قسمت ششم : استایل دهی به آبجکت ها در هر پلتفرم توی این قسمت از آموزش میپردازیم به بحث Custom Renderer قبل از هر چیزی باید بدونیم CustomRenderer چی هست و چه زمان باید بریم سراغش همینطور که در متن بالا هم قابل مشاهده هست برای هر کنترل (یا به عبارتی آبجکت) توی زمارین یک Renderer هم براش وجود داره که بهتره از همون دیفالتش استفاده کنیم اما برای جاهایی که امکان تغییر یک مشخصه از آبجکت برای ما وجود نداره باید خودمون دست به کار بشیم و تغییرات رو خودمون اعمال کنیم . نمونه هایی از جاهایی که نیاز هست از Custom Renderer استفاده کنیم : 1 - گرد کردن گوشه های کادر های ورودی کاربر (Entry) 2 - انتخاب یک پس زمینه گرادیانت برای صفحه و.... برای مثال عملی با همین گرد کردن کادر دور Entry شروع میکنیم . توی پروزه مشترک زمارین یک پوشه به اسم StyledObjects که آبجکت هایی که بهشون استایل میدیم رو اونجا ذخیره میکنیم . البته اسم پوشه کاملاً دلخواه هستش. یک کلاس داخل پوشه به اسم CSRoundedEntry بسازید که مخفف Custom Styled Rounded Entry میباشد . مشخصه هایی که برای آبجکت مد نظرتون در نظر دارید (علاوه بر مشخصه های پیشفرض آبجکت اصلی) داخل این کلاس تعریف کنید . دقت کنید این کلاس باید از آبجکت اصلی ارث بری شده باشد . به عنوان مثال : namespace GettingStarted.StyledObjects { class CSRoundedEntry : Entry { public int CornerRadious { get; set; } } } همانطور که در کد بالا قابل مشاهده است با استفاده از Entry : کلاس من از خواص Entry ارث بری شده و وارث خواص این کلاس است علاوه بر اینکه یک مشخصه به نام Corner Radious جهت میزان زاویه خمیدگی در نظر گرفتم . حالا باید دقیقاً مثل بحث قبلی که بحث DependencyServices بود باید در هر پروژه یک کلاس برای این آبجکت ایجاد نمائیم . در پروژه اندروید یک کلاس مانند زیر ایجاد میکنیم [assembly: ExportRenderer(typeof(GettingStarted.StyledObjects.CSRoundedEntry), typeof(GettingStarted.Droid.StyledObjects.CSRoundedEntry))] namespace GettingStarted.Droid.StyledObjects { class CSRoundedEntry : EntryRenderer { } } خب همونطور که در بالا هم مشاهده میشه کاستوم رندرر هم خیلی شبیه به Dependency Service ها هست با این تفاوت که چون از اینترفیس ارث بری نشده در ExportRenderer هم کلاس اصلی در پروژه ی مشترک رو ذکر میکنیم هم کلاسی که همینجا مینویسیم و به این طریق این دو کلاس رو به هم ربط میدیم . حالا در کلاس یک تابع وجود داره که باید اون رو Override کنیم به نام OnElementChanged . داخل کلاس این تابع رو اضافه میکنیم : protected override void OnElementChanged(ElementChangedEventArgs<Entry> e) { base.OnElementChanged(e); if (Control != null) { this.Control.Background = ContextCompat.GetDrawable(Context,Resource.Drawable.RoundedCornerEntry); } } با استفاده از Control شما به پراپرتی ها (مشخصات) آبجکت دسترسی دارید . این قسمت کار واقعاً نیازمند تسلط به کد نویسی هر سیستم عامل میباشد و امکان اینکه یک نسخه مشترک برای همه سیستم عامل ها بپیچیم وجود نداره . برای اینکه راحت تر بتونیم به آبجکت ها استایل بدیم و اینکه بشه روش نسبتاً مشترکی برای همه سیستم عامل ها گفت من در نسخه اندروید و UWP با استفاده از زبان کد نویسی رابط کاربری خود سیستم عامل ها یک فایل استایل ساختم و اون رو در کد لود میکنم . همونطور که در کد بالا هم مشاهده میکنید Rounded Corner Entry رو از ریسورس های برنامه لود میکنم . پس در پوشه Resources و پوشه Drawable یک فایل xml به نام RoundedCornerEntry.xml ایجاد میکنم که از طریق کد سی شارپ هم این فایل رو فراخونی کردم . اگر Build Action این فایل چیزی جز Android Resource بود بیلد اکشن رو تغییر بدید . داخل فایل استایل مورد نظر خودم رو مینویسم که به شکل زیر هست : <?xml version="1.0" encoding="UTF-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_focused="true" > <shape android:shape="rectangle"> <gradient android:startColor="@color/entry_background" android:endColor="@color/entry_background" android:angle="270" /> <stroke android:width="1dp" android:color="@color/entry_border" /> <corners android:radius="6dp" /> </shape> </item> <item> <shape android:shape="rectangle"> <gradient android:startColor="@color/entry_background" android:endColor="@color/entry_background" android:angle="270" /> <stroke android:width="1dp" android:color="#c6c6c6" /> <corners android:radius="6dp" /> </shape> </item> </selector> خب اینکه چطور این استایل رو نوشتم هم خیلی ساده اس فقط یک سرچ توی اینترنت زدم ! همین . همینطور اگه تو ریسورس بالا دقت کنید زاویه لبه های کادر رو 6dp در نظر گرفتم و کلا به پراپرتی که به عنوان نمونه اضافه کرده بودم کار نداشتم ! حالا میریم به سراغ ios : توی ای او اس هم دقیقاً مثل همون قضیه Dependency Service و مثل کاری که برای اندروید انجام دادیم مجددا یک کلاس میسازیم و تابع رو override میکنیم : [assembly: ExportRenderer(typeof(GettingStarted.StyledObjects.CSRoundedEntry), typeof(GettingStarted.iOS.StyledObjects.CSRoundedEntry))] namespace GettingStarted.iOS.StyledObjects { class CSRoundedEntry : EntryRenderer { protected override void OnElementChanged(ElementChangedEventArgs<Entry> e) { base.OnElementChanged(e); if (Control != null) { Control.Layer.CornerRadius = 6; Control.Layer.BorderWidth = new nfloat(2); Control.Layer.BackgroundColor = UIColor.FromRGBA(255, 255, 255, 204).CGColor; Control.TintColor = UIColor.FromRGBA(255, 255, 255, 178); } } } } که همونطور که مشخص هست اینجا هم کاری به کار مشخصه ای که تعریف کردیم نداشتم و باز هم زاویه رو 6 در نظر گرفتم ! حتی نمیدونم چرا اون پراپرتی رو الکی در نظر گرفتم همونطور که توی کد بالا مشخص هست با استفاده از Control.Layer به مشخصات آبجکت دسترسی داریم و میتونیم تغییرات رو اعمال کنیم حالا به سراغ UWP میریم . برای تغییر دادن آبجکت ها توی UWP یک روش بسیار ساده وجود داره . وارد msdn.com بشید سرچ کنید ObjectName Default Style in UWP به عنوان مثال دیفالت استایل مربوط به تکست باکس در این لینک قابل مشاهده هست . دیفالت استایل رو کافیه کپی کنیم و توی فایل app.XAML آنرا کپی کنید . البته ابتدا باید در این فایل چند خط کد اضافه کنید <Application.Resources> <ResourceDictionary> </ResourceDictionary> </Application.Resources> حال باید استایل را در داخل ResourceDictionary کپی کنید و تغییرات مورد نظرتون رو در استایل پیشفرض ایجاد کنید . برای جلوگیری از شلوغ شدن فایل هم پیشنهاد میکنم توی پروژه UWP یک پوشه به اسم Styles ایجاد کنید و یک فایل ResourceDictionary در این پوشه ایجاد کنید و داخل فایل app.XAML این فایل را به صورت زیر لود کنید . <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="/Styles/Dictionary1.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> برای مثال من استایل پیشفرض رو به شکل زیر تغییر دادم و در فایل Dictionary1 کپی کردم : <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <!-- Default style for Windows.UI.Xaml.Controls.TextBox --> <Style TargetType="TextBox" x:Key="StyleRoundedTextBox"> <Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}" /> <Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}" /> <Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" /> <Setter Property="Background" Value="{ThemeResource SystemControlBackgroundAltHighBrush}" /> <Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundChromeDisabledLowBrush}" /> <Setter Property="SelectionHighlightColor" Value="{ThemeResource SystemControlHighlightAccentBrush}" /> <Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" /> <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" /> <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" /> <Setter Property="ScrollViewer.HorizontalScrollMode" Value="Auto" /> <Setter Property="ScrollViewer.VerticalScrollMode" Value="Auto" /> <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" /> <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" /> <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" /> <Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="TextBox"> <Grid> <Grid.Resources> <Style x:Name="DeleteButtonStyle" TargetType="Button"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Grid x:Name="ButtonLayoutGrid" BorderBrush="{ThemeResource TextBoxButtonBorderThemeBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{ThemeResource TextBoxButtonBackgroundThemeBrush}"> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal" /> <VisualState x:Name="PointerOver"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement" Storyboard.TargetProperty="Foreground"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAccentBrush}" /> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Pressed"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="Background"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAccentBrush}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement" Storyboard.TargetProperty="Foreground"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltChromeWhiteBrush}" /> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Disabled"> <Storyboard> <DoubleAnimation Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="Opacity" To="0" Duration="0" /> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <TextBlock x:Name="GlyphElement" Foreground="{ThemeResource SystemControlForegroundChromeBlackMediumBrush}" VerticalAlignment="Center" HorizontalAlignment="Center" FontStyle="Normal" FontSize="12" Text="&#xE10A;" FontFamily="{ThemeResource SymbolThemeFontFamily}" AutomationProperties.AccessibilityView="Raw"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </Grid.Resources> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Disabled"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderContentPresenter" Storyboard.TargetProperty="Foreground"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseMediumLowBrush}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement" Storyboard.TargetProperty="Background"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledTransparentBrush}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundBaseLowBrush}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseLowBrush}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledChromeDisabledLowBrush}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledChromeDisabledLowBrush}" /> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Normal" /> <VisualState x:Name="PointerOver"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightChromeAltLowBrush}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement" Storyboard.TargetProperty="Opacity"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundHoverOpacity}" /> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Focused"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlPageTextChromeBlackMediumLowBrush}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement" Storyboard.TargetProperty="Background"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundChromeWhiteBrush}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement" Storyboard.TargetProperty="Opacity"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundFocusedOpacity}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAccentBrush}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlForegroundChromeBlackHighBrush}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="RequestedTheme"> <DiscreteObjectKeyFrame KeyTime="0" Value="Light" /> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="ButtonStates"> <VisualState x:Name="ButtonVisible"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="DeleteButton" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0"> <DiscreteObjectKeyFrame.Value> <Visibility>Visible</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="ButtonCollapsed" /> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Border x:Name="BackgroundElement" Grid.Row="1" Background="{TemplateBinding Background}" Margin="{TemplateBinding BorderThickness}" Opacity="{ThemeResource TextControlBackgroundRestOpacity}" Grid.ColumnSpan="2" Grid.RowSpan="1"/> <Border x:Name="BorderElement" CornerRadius="6" Grid.Row="1" BorderBrush="#ccffffff" Background="#b2ffffff" BorderThickness="2" Grid.ColumnSpan="2" Grid.RowSpan="1"/> <ContentPresenter x:Name="HeaderContentPresenter" x:DeferLoadStrategy="Lazy" Visibility="Collapsed" Grid.Row="0" Foreground="{ThemeResource SystemControlForegroundBaseHighBrush}" Margin="0,0,0,8" Grid.ColumnSpan="2" Content="{TemplateBinding Header}" ContentTemplate="{TemplateBinding HeaderTemplate}" FontWeight="Normal" /> <ScrollViewer x:Name="ContentElement" Grid.Row="1" HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}" HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}" VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}" IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}" IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}" IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}" Margin="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" IsTabStop="False" AutomationProperties.AccessibilityView="Raw" ZoomMode="Disabled" /> <ContentControl x:Name="PlaceholderTextContentPresenter" Grid.Row="1" Foreground="{ThemeResource SystemControlPageTextBaseMediumBrush}" Margin="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" IsTabStop="False" Grid.ColumnSpan="2" Content="{TemplateBinding PlaceholderText}" IsHitTestVisible="False"/> <Button x:Name="DeleteButton" Grid.Row="1" Style="{StaticResource DeleteButtonStyle}" BorderThickness="{TemplateBinding BorderThickness}" Margin="{ThemeResource HelperButtonThemePadding}" IsTabStop="False" Grid.Column="1" Visibility="Collapsed" FontSize="{TemplateBinding FontSize}" MinWidth="34" VerticalAlignment="Stretch"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary> حالا دوباره مثل نسخه اندروید و آی او اس کلاس مینویسیم و تابع override میکنیم به این شکل : [assembly: ExportRenderer(typeof(GettingStarted.StyledObjects.CSRoundedEntry), typeof(GettingStarted.UWP.StyledObjects.CSRoundedEntry))] namespace GettingStarted.UWP.StyledObjects { class CSRoundedEntry : EntryRenderer { protected override void OnElementChanged(ElementChangedEventArgs<Entry> e) { base.OnElementChanged(e); Control.Style = (Windows.UI.Xaml.Style)GettingStarted.UWP.App.Current.Resources["StyleRoundedTextBox"]; } } } یک نکته خیلی مهم که توی این کد بالا هست اینه که حتماً حتماً حتماً این namespace ها توی کد UWP باشه . چون هم کلمه Style هم App به صورت مشترک در خود UWP و هم در Xamarin.Forms استفاده شده و اگر حواستون نباشه به راحتی این دو تا کلاس با هم اشتباه میشن و به ارور های زمان کامپایل و ران تایم بر میخورید که حتی خیلی وقت ها هم ممکنه اصلا متوجه نشید کجا رو اشتباه کردید که به این خطا ها برخورد کردید . خب باز هم توی کد های بالا میبینید که باز هم اون Corner Radious که تعریف کردم رو ازش استفاده نکردم اما اگر شما نیاز دارید که حتما مقدار اون پراپرتی رو دسترسی داشته باشید بهش به این صورت میتونید بهش دسترسی داشته باشید : protected override void OnElementChanged(ElementChangedEventArgs<Entry> e) { base.OnElementChanged(e); if (Control != null) { var element = (GettingStarted.StyledObjects.CSRoundedEntry)e.NewElement; var rad = element.CornerRadious; } } حالا که آبجکت ما برای هر سه سیستم عامل حاضر شده توی کد های XAML صفحه مورد نظرمون کافیه که ابتدا نیم اسپیس کلاس خودمون رو به پروژه بشناسونیم : xmlns:local="clr-namespace:GettingStarted.StyledObjects" و بعد توی کد های زمل هم مثل خط زیر میشه از آبجکت خودمون استفاده کنیم و پراپرتی های مورد نظرمون رو هم به دلخواه مقدار دهی کنیم : <local:CSRoundedEntry Placeholder="passwod" FontSize="20" HeightRequest="50" IsPassword="True" CornerRadious="6"/>
  21. 4 پسند
    سلام؛ داشتن یک کیبورد اختصاصی می تواند برای خیلی ها مفید و کارآمد باشد، کیبوردی که تنها برای یک عملیات یا برنامه خاص، فعالیت شما را ساده تر و حرفه ای تر می کند، یک کیبورد مخصوص بازی، کیبورد پخش چند رسانه ای، کیبورد برای کنترل رسپبری پای و یا حتی یک کلید برای تایپ ; در محیط ویژوال استدیو! خب، به موارد زیر برای انجام این پروژه نیازمندیم: 1. یک برد آردوئینو که از USB پشتیبانی کند و دارای پردازنده ATmega32u4 باشد! (مانند:Leonardo, Micro, یا Due board). 2. کابل USB 3. سیم 4. بردبورد 5. کلید فشاری در بعد نرم افزاری: 1. IDE Arduino از لحاظ برنامه نویسی با کار پیچیده ای روبرو نیستیم، می توانید یک کلید تعریف کنید که تنها حرف R را تایپ کند یا یک کلید ترکیبی از Ctrl + C بسازید که عملیات کپی را انجام دهد. حتی به سادگی می توانید عملیات را زمان بندی کنید تا با فشار کلید، یک سری عملیات ها (فشار کلید) انجام شود. در اینجا ما برای فهم بهتر پروژه دو مثال می زنیم، ابتدا بیایید یک کلید را به برد خود متصل کنیم! این تصویر هم توسط Fritzing ایجاد شده! که بعدا مفصل در موردش صحبت خواهیم کرد. همانطور که می بینید، ما 2D را به وسیله دکمه به GND متصل می کنیم تا عملیات فیزیکی فشار دکمه کیبورد را ایجاد کنیم. اکنون بورد خود را به وسیله USB به رایانه خود متصل کنید و IDE Arduino رو اجرا کنید. در گام اول، کتابخانه کیبورد را به پروژه با تایپ عبارت زیر اضافه می کنیم: #include "Keyboard.h" در void setup، پین 2 را به عنوان ورودی تعریف می کنیم و کیبورد را فراخوانی می کنیم، با این فراخوانی، برد شما به عنوان یک کیبورد شناسایی خواهد شد! void setup() { // make pin 2 an input and turn on the // pullup resistor so it goes high unless // connected to ground: pinMode(2, INPUT_PULLUP); // initialize control over the keyboard: Keyboard.begin(); } و حالا در حلقه، با توجه به اینکه در حال فشار دکمه هستیم یا خیر، کلید مورد نظر را فراخوانی می کنیم. برای تشخیص در حال فشرده شدن کلید می توان از یک شرط ساده استفاده کرد: void loop() { while (digitalRead(2) == HIGH) { // do nothing until pin 2 goes low delay(500); } خب اکنون می خواهیم کلید ; را بسازیم: Keyboard.press(';'); delay(100); Keyboard.releaseAll(); به همین سادگی ما یک کلید را ساختیم که با فشار آن و نگه داشتنتش، هر دهم ثانیه، یکبار ; را تایپ می کند. اما اگر بخواهید از کلید Ctrl استفاده کنید، باید آن را تعریف کنید، در کیبوردهایی که از ویندوز (و همچنین لینوکس) پشتیبانی می کنند، این کلید به صورت زیر تعریف می شود: char ctrlKey = KEY_LEFT_GUI; هر چند لازم نیست (آخه کاربرای مک کجا از این کارا می کنند؟! ) اما برای مک به صورت زیر است: char ctrlKey = KEY_LEFT_CTRL; دیگر چیزی تغییر نمی کند جز اینکه باید قبل از کلید c، کلید ctrl را فشار دهیم! // Copy: Keyboard.press(ctrlKey); Keyboard.press('c'); delay(100); Keyboard.releaseAll(); به همین سادگی! می توانید عملیات های پیچیده دیگری رو هم تعریف کنید! #لذت_ببرید اما کدها به صورت کامل: تک کلید: #include "Keyboard.h" void setup() { // make pin 2 an input and turn on the // pullup resistor so it goes high unless // connected to ground: pinMode(2, INPUT_PULLUP); // initialize control over the keyboard: Keyboard.begin(); } void loop() { while (digitalRead(2) == HIGH) { // do nothing until pin 2 goes low } delay(500); Keyboard.press('n'); delay(100); Keyboard.releaseAll(); } و برای کپی: #include "Keyboard.h" void setup() { // make pin 2 an input and turn on the // pullup resistor so it goes high unless // connected to ground: pinMode(2, INPUT_PULLUP); // initialize control over the keyboard: Keyboard.begin(); } void loop() { while (digitalRead(2) == HIGH) { // do nothing until pin 2 goes low } delay(1000); // Copy for Win/Linux: Keyboard.press(ctrlKey); Keyboard.press('n'); delay(100); Keyboard.releaseAll(); }
  22. 4 پسند
    تشکر از پوریا بابت آموزش . یک سری نکات : اگر موقع ایجاد ماشین مجازی توی VirtualBox گزینه های 64 بیتی نداشتید دلیل فعال بودن هایپر وی هست قبل انجام آموزش هایپر وی رو به روش ذکر شده توی مطلب غیر فعال کنید از محیط No Hyper-V بوت کنید ویندوز رو . برای اشتراک گذاری فایل بین ویندوز و مک خیلی ساده هست . گزینه سرچ بالا سمت راست صفحه دسکتاپ مک رو انتخاب کنید ، برنامه Terminal رو جستجو و اجرا کنید . بعد دستور زیر را تایپ کنید ipconfig getoption en0 router یک آدرس آی پی احتمالاً با شروع 10 مثل 10.0.2.2 به شما میده که توی Finder > Go > Connect to server دقیقاً همون رو تایپ کنید بعد یوزر ویندوز و پسوردتون رو بزنید (اگر Pin هم دارید باز هم باید پسورد رو وارد کنید Pin رو قبول نمیکنه) به فولدر های شیر شده از ویندوز دسترسی دارید . برای شیر کردن فولدر کافیه توی ویندوز روی یک پوشه راست کلیک کنید بعد Properties سربرگ Sharing وارد شوید روی Advanced Sharing کلیک کنید سپس تیک Share this folder را بزنید یک نام برای فولدر در حالت Share انتخاب کنید و سپس اوکی کنید . (این کار برای درایو ها نیز قابل انجام است اما جهت امنیت سایر اطلاعات و مخفی ماندن از دید سایر نود های موجود در شبکه بهتر است یک پوشه مشترک تنها برای این امر ایجاد کنید) برای نصب کردن xcode اول حتما فایلش رو توی محیط مک کپی کنید سعی نکنید از روی شبکه مستقیم بخواید اجراش کنید . ترجیحاً روی دسکتاپ مک کپی کنید بعد اجرا کنید منتظر بمونید تا نصب بشه . بعد ویژوال استدیو رو هم به همین روش نصب کنید (تقریباً 2 گیگ دانلود میکنه و برای کار ما فقط Xamarin.Ios کافیه) بعد از نصب هر دو تا مورد مک رو Shutdown کنید به تنظیمات ماشین مجازی تو Virtualbox برید به تنظیماتش بعد قسمت Network توی سربرگ Adapter 2 رفته و تنظیمات زیر را در این قسمت ست کنید . حال مجدداً مک را راه اندازی کنید . حال Remote login را جستجو کنید و آنرا اجرا کنید . سپس تیک Remote login را بزنید و گزینه All Users را انتخاب کنید . بعد از راه اندازی مک به ویژوال استدیوی ویندوز رفته و از tools -> Options Xamarin -> ios settings حال گزینه Find Xamarin Mac را بزنید و Next کنید حال باید به صورت خودکار مک شناسایی شود . روی آن دوبار کلیک کنید و یوزر نیم و پسورد مک را وارد کنید کار تمام است . در صورت مشاهده پیامی مبتنی بر لایسنس xcode در ترمنینال عبارت های زیر را تایپ کنید . sudo xcode-select -s /XcodePath/Xcode-Beta.app/Contents/Developer sudo xcodebuild -license به عنوان مثال اگر در همان صفحه دسکتاپ فایل نصب را کپی و اجرا کرده باشید (که مسیر نصب هم همانجا خواهد بود) دستور اول به صورت زیر خواهد بود sudo xcode-select -s /Users/Usernae/Desktop/Xcode-Beta.app/Contents/Developer بخ جای xcode-beta.app هم اسم فایل برنامه رو باید بنویسید
  23. 4 پسند
    آموزش برنامه نویسی با Xamain.Forms قسمت چهارم : کد نویسی اختصاصی هر سیستم عامل ! با توجه به امکانات بسیار عالی زمارین فرم باز هم در بسیاری از قسمت ها نیاز داریم که از امکانات اختصاصی پلتفرم ها استفاده کنیم یکی از بارز ترین این استفاده ها نوشتن کد های مربوط به پخش مدیا در پس زمینه میباشد . باید بگم که این قسمت از آموزش یکی از مهم ترین و اصلی ترین قسمت های آموزش میباشد پس به دقت مراحل را انجام دهید . به عنوان یک نمونه خیلی ساده در این آموزش میخواهیم یک پیام خوش آمد ساده به کاربر نشان دهیم اما بسته به اینکه برنامه در چه پلتفرمی اجرا میشود پیغام متفاوتی نمایش داده شود . برای انجام این کار ابتدا نیاز به ساخت یک Interface داریم . در پروژه مشترک زمارین ابتدا یک پوشه به نام دلخواه ایجاد نمائید به عنوان مثال Services یا Classes در پوشه ایجاد شده یک کلاس به نام دلخواه مانند WelcomeMsg بسازید . کلاسی به صورت زیر برای شما ایجاد میشود . class WelcomeMsg { } حال کلاس فوق را به صورت تغییر دهید تا تبدیل به interface شود. public interface IWelcomeMsg { } به دلیل اینکه قواعد کد نویسی سی شارپ را نیز رعایت کرده باشیم ابتدای نام یک I (آی) بزرگ اضافه میکنیم که بیانگر اینترفیس باشد . حال درون آن به تعریف توابعی که در این اینترفیس موجود میباشد میپردازیم . در اینجا تنها کافیست که به امضای تابع و متغیر های پابلیک تعریف شده اشاره کنید و نیازی به نوشتن هیچ کدی نیست . public interface IWelcomeMsg { string GetWelcomeMessage(); } خب به همین سادگی اینترفیس ما ساخته شده و آماده است ! حال باید در تمامی پروژه های مرتبط به تک تک سیستم عامل ها یک پوشه با نام پوشه ای که در پروژه ساختید ایجاد نمائید و کلاسی نیز با همان نام ایجاد نمائید . (هرچند اجباری در این نام گذاری ها نیست اما به جهت جلوگیری از پیچیده شدن کار بهتر است از همین شیوه استفاده نمائید) به عنوان مثال در پروژه UWP در پوشه Services یک کلاس با نام WelcomeMsg ایجاد مینمائیم . پس از ساخته شدن فایل لازم هست که کلاس خودمون رو به اینترفیس ساخته شده متصل نمائیم و برای این کار از خاصیت ارث بری سی شارپ استفاده میکنیم class WelcomeMsg : IWelcomeMsg { } قطعا خواهید دید که از IWelcomeMsg ارور گرفته میشود . اشاره گر موس را روی IWelcomeMsg قرار دهید و روی علامت چراغ زرد رنگ ظاهر شده کلیک کنید و سپس Implement Interface را انتخاب کنید . حال به صورت خودکار توابع تعریف شده در اینترفیس اینجا تعریف خواهند شد . class WelcomeMsg : IWelcomeMsg { public string GetWelcomeMessage() { throw new NotImplementedException(); } } خط throw new NotImplementedException(); به این منظور به صورت خودکار ایجاد میشود تا در صورت فراخوانی تابع Debugger به خطا برخورد کند و به شما اخطار دهد که این تابع کد نویسی نشده ! در اینجا به این خط نیازی نداریم و آنرا پاک میکنیم و به جای آن پیام خود را مینویسیم مانند : return "Welcome to our UWP Xamarin App"; حال در خط اول کلاس پیش از namespace و بعد از using ها این خط را اضافه میکنیم : [assembly: Xamarin.Forms.Dependency(typeof(XFCalc.UWP.Services.WelcomeMsg))] با توجه به کد بالا متوجه خواهید شد که Attribute موسوم به Dependency در زمارین فرم را به کلاس پروژه خود متصل نمودیم . به این ترتیب بین اینترفیس در پروژه مشترک و کلاس ما در هر سیستم عامل ارتباط برقرار میشود . حال به صورت مشابه همین کلاس را در اندروید نیز خواهیم ساخت به صورت زیر : [assembly: Xamarin.Forms.Dependency(typeof(XFCalc.Droid.Services.WelcomeMsg))] namespace XFCalc.Droid.Services { class WelcomeMsg : IWelcomeMsg { public string GetWelcomeMessage() { return "Welcome to our Android Xamarin App"; } } } حال در زمل صفحه اصلی برنامه در پروژه مشترک یک Label جهت نمایش پیام به کاربر ایجاد میکنیم <ContentPage.Content> <Grid> <Label VerticalOptions="Center" HorizontalOptions="Center" x:Name="LabelMsg"/> </Grid> </ContentPage.Content> حال در قسمت کد سی شارپ همین صفحه از طریق کد زیر پیام خود را مرتبط با سیستم عاملی که برنامه در آن در حال اجراست دریافت میکنیم و به کاربر نمایش میدهیم . LabelMsg.Text = DependencyService.Get<IWelcomeMsg>().GetWelcomeMessage(); در آموزش های بعدی با کاربرد های بسیار گسترده تری از این قابلیت آشنا خواهید شد و تعدادی کلاس هایی که پیش از این نوشته ام رو به اشتراک میگذارم .
  24. 4 پسند
    با سلام و عرض ادب و احترام خدمت شما. امروز با آموزش اولیه ی انتیتی فریمورک کور در خدمت شما هستیم. در این آموزشی شما : با مفاهیم پایه ای ORM و انتیتی فریمورک آشنا خواهید شد + با یک آموزش پروژه محور، راه اندازی انتیتی فریمورک کور و عملگر های اصلی آن را فرا خواهید گرفت. همانطور که می دانید، انتیتی فریمورک یک نوع ORM است. (از نظر خودم بهترین ORM) که اجازه ی ارتباط و مدیریت دیتابیس را در اختیارتان قرار می دهد. انتیتی فریمورک کور همان انتیتی فریمورک است که به صورت فراپلتفرمی اجرا شده است. این ORM میتواند در پروژه های دات نت فریمورک، زامارین، دات نت کور، ویندوز اپلیکیشن و ... روی هر پلتفرمی اجرا شود! ORM چیست؟ ORM (Object Relational Mapping) یک لایه مترجم بین زبان برنامه‌نویسی و پایگاه داده رابطه‌ای است که این دو را به هم تبدیل می‌کند و در عمل باعث می‌شود که این دو حیطه کاملا متفاوت زبان یکدیگر را به خوبی بشناسند و با هم تبادل اطلاعات داشته باشند. یک ORM قوی ، برنامه را از نوع پایگاه داده استفاده شده، جدا می‌کند. این کار باعث می‌شود که استقلال نسبت به نوع پایگاه داده حفظ شود. ORM ارتباط های دایمی و احتمالا پیچیده با پایگاه داده را انجام می دهد و نیازی به انجام اعمال تکراری وکد نویسی هایی تکراری توسط برنامه نویس در هر بار ذخیره فیلد و رکورد جدید و بازیابی اطلاعات و...نیست.از طریق ارتباطی که بوسیله ORM بین اشیاء و پایگاه داده ایجاد می شود می توان اطلاعات اشیاء را با صدا زدن یک متد در پایگاه داده ی خود ذخیره کنید. این ساده سازی که توسط ORM فراهم می شود باعث میشودبا کدهای کمتری کارهایی نظیر بازیابی اطلاعات را انجام دهیم وبعدها اگه خواستیم تغییراتی اعمال کنیم به راحتی بتونیم بازسازی وتغییرش بدیم. ORM محدود به هیچ زبان خاصی نیست و تنها یک تکنیک و سیستم است که می تواند در زبانهای مختلف پیاده سازی شود . چند نوع ارتباط اولیه با دیتابیس داریم؟ 1-Database First:در این روش ابتدا دیتابیس طراحی و پیاده سازی می شود و بعد از آن انتیتی فریمورک به وسیله ی ویزارد، کلاس ها و موارد دیگر ارتباط با دیتابیس را می سازد. 2-Model First: در این روش ابتدا به وسیله ی کلاس دیاگرام، مدل برنامه طراحی می شود و انتیتی فریمورک با آن دیتابیس و کلاس ها و موارد دیگر را می سازد. 3- Code First: در این روش ابتدا کلاس ها و منطق ابتدایی برنامه نوشته میشود، سپس با انتیتی فریمورک این کلاس ها و آبجکت ها به صورت فیلد ها و رکورد های دیتابیس در میاورد. در این روش برنامه نویس فقط وظیفه ی کد نویسی را دارد و این ORM است که دیتابیس را ساخته و آن را مدیریت میکند. در انتیتی فریمورک فقط اتصال اولیه ی دیتابیس راه های مختلف دارد اما از اینجا به بعد، همه چیز یکسان است. مفاهیم پایه ای: انتیتی(Entity): انتیتی یک کلاس ساده است که پس از فرایند مایگریت به جدول های دیتابیس تبدیل می شود. همچنین این کلاس ها در ارتباط کد فرست با دیتابیس مارا یاری خواهند کرد. DbSet: یک کالکشن در حافظه که مقادیر دیتابیس را در خود دارد. با کوئری های Linq میتوانیم به آن دسترسی داشته باشیم و اعمال add(inset),Delete,Update,Select را در آن انجام دهیم. مایگریتشن(Migration): فرایندی که ORM انتیتی ها را به کد های ساخت و یا تغییرات دیتابیس تبدیل می کند. مایگریت(Migrate): اجرای دستورات مایگریشن و اعمال تغییرات و یا ساخت دیتابیس. در ادامه به صورت پروژه محور با انتیتی فریمورک کور (به صورت Code First) آشنا خواهیم شد.
  25. 4 پسند
    سلام. برای Badge اول باید داخل منیفست تیکش رو بزنی بعدش حالا کد هاش رو بزن var type = BadgeTemplateType.BadgeNumber; var xml = BadgeUpdateManager.GetTemplateContent(type); var elements = xml.GetElementsByTagName("badge"); var element = elements[0] as Windows.Data.Xml.Dom.XmlElement; //Add your value here. int val = 10; element.SetAttribute("value", val.ToString()); var updator = BadgeUpdateManager.CreateBadgeUpdaterForApplication(); var notification = new BadgeNotification(xml); updator.Update(notification); داخل متغیر Val هرچی بزنی، به صورت عدد Badge نشون میده.
  26. 3 پسند
    با سلام . حتماً همیشه در برنامه هایی که تا کنون نوشته اید با مشکل تغییر در رابط کاربری مواجه بوده اید. اینکه یک بخش از رابط کاربری را بخواهید حذف کنید تغییر دهید و.... آزار دهنده به نظر میرسد چون بعد از تغییر رابط کاربری اسامی اشیاء را باید به گونه ای تغییر دهید که در بک کد های شما نیز وجود دارد مثلا لیستی با نام Lst را در بک کد مقدار دهی نموده اید پس از تغییر رابط کاربری باید به یک لیست ویو حتما همین نام را بدهید . وای به روزی که اصلا نفهمید اون آبجکت چی بوده! و اصلا این قسمت کدتون داره چی کار میکنه. خب برای حل این مشکل یک روش کد نویسی وجود داره که شاید با نام MVVM یا MVC به گوشتون خورده باشه . اما MVVM مخفف چیه ؟ کلمه MVVM از سه بخش تشکیل شده : M : مدل (Model) V : ویو (View) و VM : ویو مدل (View Model) بخش مدل فقط شامل کلاس های ما میشه. به عنوان مثال من توی یک برنامه موسیقی یک کلاس دارم مربوط به آلبوم خواننده که شامل اسم خواننده ، سال انتشار آلبوم ، تعداد ترک های آلبوم ، ترانه سرایان ، تنظیم کنندگان ، آی دی آلبوم و.... میباشد که به این کلاس ها که در آینده باهاشون توی رابط کاربری سر و کار هم داریم میگیم مدل. بخش ویو : این بخش از همه آشنا تره همون رابط کاربری صفحه است که با Xaml به عنوان مثال توی UWP و WPF میسازیم . اما بخش View Model : این بخش ارتباط دهنده مدل ها و ویو ها به هم دیگه هست . این بخش تا حدودی شبیه همون بک کد های کثیف خودمونه ولی یه تفاوت هایی داره که بعداً متوجه میشیم . توی فرآیند اجرای یک برنامه اول ویو لود میشه -> بعد ویو مدل رو فراخونی میکنه و مقادیر رو ازش میگیره و با معجزه بایندینگ به نمایش در میاره -> ویو مدل هم که در صورت لزوم به مدل ها دسترسی داره . خب حالا برای تست یه پروژه میسازیم به اسم ColorMVVM که در اینجا من پروژه رو از نوع C# UWP میسازم . سپس توی سولوشن اکسپلورر دو تا Folder به اسم های View و ViewModel میسازم . ادامه مطلب رو توی پست بعدی مینویسم .
  27. 3 پسند
    با سلام. تا کنون با مفاهیمی همچون View , ViewModel , Model, Command و Binding و انواع آن آشنا شدیم . در این قسمت میخواهیم با Converter آشنا شویم . به عنوان مثال متغیر public bool IsBusy در ویو مدل را میخواهیم تبدیل به Visibility برای یک ProgressRing نماییم . به صورت مستقیم این کار ممکن نیست پس یا باید در ویو مدل متغیر دیگری با نوع Visibility در نظر بگیریم یا یک کانورتر بنویسیم و آنرا در زمل فراخوانی کنیم . در اینجا از هر دو روش استفاده خواهیم کرد. روش اول (تبدیل در داخل ویو مدل) : ابتدا متغیر IsBusy را به ویو مدل خود می افزائیم : private bool _isbusy; public bool IsBusy { get => _isbusy; set { _isbusy = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsBusy")); } } حالا یک متغیر از نوع Visibility نیازمندیم که آنرا نیز ایجاد میکنیم . private Visibility _loadindivis; public Visibility LoadingIndicatorVisibility { get => _loadindivis; set { _loadindivis = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("LoadingIndicatorVisibility")); } } حالا برای ایجاد ارتباط بین دو متغیر در بخش set متغیر IsBusy مقدار LoadingIndicatorVisibility را نیز ست میکنیم . public bool IsBusy { get => _isbusy; set { _isbusy = value; if (value) LoadingIndicatorVisibility = Visibility.Visible; else LoadingIndicatorVisibility = Visibility.Collapsed; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsBusy")); } } به این صورت حالا در هر جا که بخواهیم Visibility یک شیء را با تغییر IsBusy تغییر دهیم کافیست Visibility="{Binding LoadingIndicatorVisibility, Mode=OneWay}" را استفاده کنیم . اما در صورتیکه تعداد متغیر های نیازمند تبدیلمان زیاد شوند دائماً باید بر تعداد متغیر ها بیافزاییم در حالیکه به عنوان مثال همه آنها تعداد bool به Visibility هستند. در این موارد از یک Converter واحد برای همیشه استفاده خواهیم کرد. خوبی این روش هم علاوه بر سادگی این هست که در پروژه های آینده هم در صورت نیاز به این نوع کانورتر دیگر نیاز به نوشتن مجدد آن نخواهد بود هر چند که کار دشوار هم نیست ! روش دوم (استفاده از Converter یا مبدل در زمل): برای استفاده از این روش ابتدا متغیر های از نوع Visibility که پیش از این تعریف نمودیم را حذف میکنیم چون دیگر به آنها نیازی نداریم . سپس در روت پروژه یک پوشه جدید به نام Converters ایجاد میکنیم . در پوشه ایجاد شده یک کلاس جدید با نام BoolToVisibilityConverter ایجاد میکنیم و سپس آنرا از اینترفیس IValueConverter ارث بری میکنیم : class BoolToVisibilityConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { throw new NotImplementedException(); } public object ConvertBack(object value, Type targetType, object parameter, string language) { throw new NotImplementedException(); } } این کلاس حال دارای دو تابع Convert و ConvertBack میباشد که در اینجا ما فقط با تابع Convert سر و کار داریم . در تابع کانورت Value را دریافت میکنیم و سپس (در صورت نیاز با کمک Parameter و Language) تبدیلات را انجام میدهیم. در این آموزش فقط با value کار میکنیم و باید این مورد را در نظر داشته باشید که مقدار parameter و language قابل Bind نیستند (از نوع DependencyProperty نیستند) جهت اطلاعات بیشتر در مورد این موضوع جستجو کنید . با توجه به نیازمان تابع کانورت را به صورت زیر تبدیل مینماییم : public object Convert(object value, Type targetType, object parameter, string language) { var val = System.Convert.ToBoolean(value); if (val) return Visibility.Visible; else return Visibility.Collapsed; } حال در زمل یک پراگرس رینگ جهت تست این مبدل اضافه میکنیم <Page.DataContext> <VM:MainViewVM/> </Page.DataContext> <Grid Background="{Binding ColorName}"> <Grid VerticalAlignment="Center" HorizontalAlignment="Center"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <TextBox Grid.Row="0" Text="{Binding ColorName, Mode=TwoWay}" BorderThickness="2" VerticalAlignment="Center" HorizontalAlignment="Center" Width="200"/> <Button Grid.Row="1" Content="About" Command="{Binding AboutCmd}" IsEnabled="{Binding AboutCmd.CanExecuteFunc, Mode=OneWay}" Margin="0,5" Width="120" HorizontalAlignment="Center"/> </Grid> <ProgressRing Visibility="{Binding IsBusy,Converter={StaticResource BoolToVisibilityConverter}, Mode=OneWay}" IsActive="True" Width="100" Height="100"/> </Grid> بدون شک در بخش Visibility="{Binding IsBusy,Converter={StaticResource BoolToVisibilityConverter}}" به ارور بر میخوریم به این دلیل که ریسورس این کانورتر را به زمل اضافه نکرده ایم. پس در ریسورس های صفحه این مورد را اضافه میکنیم : <Page.Resources> <Converter:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/> </Page.Resources> حال در ویومدل جهت دیدن تغییرات این تغییرات را اعمال میکنیم . public MainViewVM() { AboutCmd = AppCommand.GetInstance(); AboutCmd.ExecuteFunc = ShowAbout; IsBusy = false; } حال در کلیک کلید About این تغییرات را اعمال کنید . private async void ShowAbout(object obj) { //await new MessageDialog("I am learning MVVM").ShowAsync(); IsBusy = true; await Task.Delay(5000); IsBusy = false; } حال با اجرای برنامه و زدن کلید about قادر به مشاهده پراگرس رینگ برای مدت 5 ثانیه خواهید بود.
  28. 3 پسند
    توی این قسمت باید ویومدلمون رو تکمیل کنیم و ویو رو بسازیم . خب ابتدا توی ویو مدل این پراپرتی ها رو ایجاد میکنیم : class MainViewVM : INotifyPropertyChanged { private string _colorname; public event PropertyChangedEventHandler PropertyChanged; public string ColorName { get => _colorname; set { _colorname = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ColorName")); } } } توی ویژوال استدیو 2015 به قبل اگه استفاده میکنید دستور get رو به این حالت تغییر بدید : get { return _colorname; } تا ارور برطرف بشه . در اینجا یک پراپرتی پابلیک جهت ارتباط با View و یک پراپرتی پرایوت جهت نگه داری مقادیر ورودی و خروجی این پراپرتی ایجاد کرده ایم . به این شکل که هر وقت بخواهیم مقدار ColorName رو بخوانیم ابتدا مقدار _colorname را دریافت میکنیم و سپس مقدار را بر میگردانیم و هنگام مقدار دهی ابتدا مقدار ورودی را در متغیر پرایوت ذخیره میکنیم و سپس ایونت PropertyChanged را فراخوانی میکنیم و در ورودی تابع نام متغیری که مقدارش تغییر کرده را وارد مینماییم . جهت اصولی تر شدن کار هم پیش از اینکه مقدار رو تغییر بدید و ایونت را فراخونی کنید میتونید اول چک کنید که مقدار value با مقدار _colorname متفاوت هست یا خیر و در صورت متفاوت بودن مقادیر تغییرات را ست کنید . خب ویو مدل ما تکمیل هست . حالا سراغ ویو میرویم . داخل ویو یک تکست باکس اضافه میکنیم . <TextBox Text="{Binding ColorName, Mode=TwoWay}" BorderThickness="2" VerticalAlignment="Center" HorizontalAlignment="Center" Width="200"/> همانطور که مشاهده میکنید مقدار Text را با بایندینگ به ویو مدل و پراپرتی مورد نظرم مرتبط کردم اما Mode توی بایندینگ سه نوع مد داریم . One Time / One Way / Two Way حالت پیشفرض بایندینگ One Time هست. به این معنی که یک بار از پراپرتی مقدارش رو دریافت میکنه و دیگه تغییر نمیکنه . مثلاً اگه ColorName مقدار Red رو برگردونه همیشه مقدارش Red باقی میمونه (با اینکه مقدار Color Name توی ویو مدل تغییر میکنه توی ویو تغییر نمیکنه* حالت OneWay یعنی هر وقت توی ویو مدل مقدار تغییر کرد توی رابط کاربری تغییر کنه ولی مثلا من اگه دستی توی این تکست باکس چیزی بنویسم تغییر من باعث تغییر مقدار ColorName در ویو مدل نمیشه . حالت TwoWay دقیقاً همون حالت OneWay هست با این تفاوت که مثلا من اگه مقدار داخل تکست باکس رو تغییر بدم توی ویو مدل هم تغییر میکنه . (مثلاً از این طریق میتونید یک فرم ثبت نام ساده رو فقط با 3 یا 4 تا پراپرتی پابلک ساده بسازید . ) در اینجا من از حالت TwoWay استفاده کردم چون میخوام مقدار تغییر کنه . حالا به گرید اصلی صفحه بک گراند میدم . <Grid Background="{Binding ColorName}"> <TextBox Text="{Binding ColorName, Mode=TwoWay}" BorderThickness="2" VerticalAlignment="Center" HorizontalAlignment="Center" Width="200"/> </Grid> خب برنامه ما به اتمام رسید . حالا به App.Xaml.Cs بروید و صفحه ابتدایی برنامه را تغییر دهید . در متد protected override void OnLaunched(LaunchActivatedEventArgs e) خط زیر را rootFrame.Navigate(typeof(MainPage), e.Arguments); به صورت زیر تغییر دهید : rootFrame.Navigate(typeof(MainView), e.Arguments); و حالا برنامه را اجرا کنید . پس از اجرای برنامه نام یک رنگ را به انگلیسی در تکست باکس وارد نمایید و محلی خارج از تکست باکس کلید کنید . رنگ پس زمینه برنامه به رنگ تایپ شده تغییر میکند . در صورتی که متن شما اسم یک رنگ نباشد رنگ پیش فرض ویندوز به پس زمینه اعمال میشود. تا به این قسمت فرا گرفتیم که چگونه یک ویو و ویو مدل را به هم ارتباط دهیم . تفاوت انواع بایندینگ را متوجه شدیم و با مفهوم INotifyPropertyChanged آشنا شدیم . در قسمت های بعدی قدری با موارد حرفه ای تر سر و کار خواهیم داشت سورس کد برنامه
  29. 3 پسند
    خب تا به اینجای کار فقط با یه سری مفاهیم اونم نه چندان ملموس آشنا شدیم یه پروژه هم ساختیم با دو تا پوشه . برای اینکه کارمون منظم تر باشه توی پوشه View یک Blank Page ایجاد میکنیم به نام MainView. به صورت دل به خواه نام گزاری های خودتون رو هدفمند کنید من برای فایل هایویو پسوند View برای فایل های ViewModel از پسوند VM استفاده میکنم و برای مدل ها هم از پسوند Model . هر صفحه (ویو) که میسازیم یک ViewModel هم باید براش بسازیم . البته توجه داشته باشید که آیه ای جهت ساخت ویو مدل نازل نشده! اگر پیجی مثل About میخواید بسازید کهبه بک کد نیاز نداره یا خیلی محدود هست بک کدش میتونید از این کار صرف نظر کنید ولی فراموش نکنید این کار رو فقط برای ویو هایی انجام بدید که بک کد ندارند. خب پس تو پوشه ViewModel یک کلاس با نام MainViewVM یا MainVM یا هر نام دلخواهی بسازید . من از نام استفاده میکنم . خب حالا نوبت به ارتباط دادن View به ViewModel میرسه . همونطور که کمی قبل تر اشاره کردم ویو مسئول فراخوانی ویو مدل هست . پس به کد های Xaml مربوط به MainView مراجعه میکنیم و این سه خط کد را زمل اضافه میکنیم : <Page.DataContext> <VM:MainViewVM/> </Page.DataContext> خب بعد از اضافه کردن این سه خط کد بدون شک ویژوال استدیو ارور میده بهتون چون VM رو اصلا تعریف نکردیم چی هست . برای تعریف خودکارش با موس روی VM:MainViewVM برید تا علامت چراغ زرد رنگ بیاد و Show Potential Fixes رو بزنید . سپس Add xmlns using:ColorMVVM.ViewModel رو انتخاب کنید و حالا ارور ویژوال استدیو بر طرف میشه و به ابتدای کد زمل شما این خط اضافه میشه . xmlns:VM="using:ColorMVVM.ViewModel" معمولا توی پروژه های بزرگ ممکنه ارور همچنان سر جاش بمونه یا ارور دیگه ای ظاهر بشه که با بیلد کردن پروژه مشکل حل میشه . خب حالا میریم به سراغ ViewModel . کلاس ویو مدل رو باز میکنیم و کلاسش رو از نوع INotifyPropertyChanged ارث بری میکنیم به این صورت : class MainViewVM : INotifyPropertyChanged { } از اونجایی که باز هم INotifyPropertyChanged رو نگفتیم کلاسش چیه بهتون ارور میده که با بردن موس روی کلمه و زدن Show Potential Fixes پیشنهاد using System.ComponentModel; رو به شما میده که انتخاب کنید تا به صورت خودکار رفرنسش به صفحه اضافه بشه . اما مجدداً ارور جدیدی به همین INotifyPropertyChanged داده میشه که مربوط به Implement Interface میشه . در نهایت کلاسی به شکل زیر خواهیم داشت : class MainViewVM : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; } اما INotifyPropertyChanged چیست ؟ همانطور که از نام این اینترفیس کاملاً پیداست تغییر یک Property رو با ما گزارش میده. این تغییرات رو از طریق ایونتی که ساختیم با نام PropertyChanged به ما گزارش میده . ما معمولا مستقیماً با این ایونت سر و کار نداریم . در صورت فراخوانی شدن این ایونت رابط کاربری به صورت خودکار تغییر را دریافت نموده و تغییر لازم را در رابط کاربری ایجاد میکنه (معجزه بایندینگ که گفته بودم) خب تا به این جای کار یک پروژه ساختیم پوشه های ViewModel و View رو ایجاد کردیم . یک ویو و یک ویو مدل ایجاد کردیم و ارتباط بین ویو و ویو مدل رو برقرار کردیم همچنین خاصیت INotifyPropertyChanged رو به ویو مدل خودمون دادیم تا در صورت ایجاد هر گونه تغییر توی مقادیر گزارشش رو در ویو بتونیم دریافت کنیم .
  30. 3 پسند
    با سلام اواخر سال 95 نسخه ی نهایی ویژوال استودیو2017 عرضه شد که دارای باگ ها و مشکلات عجیب و غریبی بود. هنوز هم بعد از آمدن تعداد زیادی آپدیت کوچک، باز هم مشکلاتی دارد. در ادامه با چند مشکل بسیار پیش آمده در ویژوال استودیو را به همراه راه حل برسی خواهیم کرد. 1-نصب: مشکلات گرفتن پکیج به صورت آفلاین: وقتی که شما تلاش به گرفتن پکیج ویژوال استودیو به صورت آفلاین میکنید، ممکن است با مشکلاتی همراه شوید(پکیج کامل حدود 21-23 گیگ است). برای گرفتن پکیج آفلاین ویژوال استودیو پیشنهاد می شود از یک اینترنت پر سرعت به همراه VPN استفاده شود. 2-نصب: نصب پکیج آفلاین: امکان دارد که موقع نصب پکیج آفلاین با مشکلاتی روبرو شوید. این مشکلات معمولا به صورت Error آخر نصب نمایان می شوند و بدون Repair و Modify شما قادر به باز کردن ویژوال استودیو نخواهید بود. دلیل این مشکل میتواند کامل نبودن پکیج آفلاین یا آپدیت نبودن آن پکیچ باشد. پیشنهاد می شود هنگام نصب VPN و اینترنت پرسرعت داشته باشید تا پکیج های مشکل دار به صورت آنلاین نصب شوند. گرچه بعد از نصب با Modify و سپس Repair مشکلتان حل خواهد شد. 3-نصب: گیر کردن روی یک پکیج خاص: فی الواقع دلیل اصلی رخ دادن این مشکل را نمیدانم، ولی حدس میزنم عدم توانایی ویژوال استودیو در دپلوی کردن برخی پکیج ها دلیل این مشکل باشد. گزارش شده است که در برخی پکیج ها که به صورت استند الون نصب شده اند و یا از نصب نسخه ی قبلی ویژوال استودیو باقی مانده اند، در نصب به مشکل می خورند. لذا به پاک کردن آن پکیج ها اقدام کنید. در غیر این صورت حدود 6 ساعت صبر کنید تا مطمئن شوید که نصب جلوتر نمیرود. بعد از آن Task manager را باز کنید بخش Details دنبال آیتم VSinstaller باشید. روی آن کلیک راست کنید و Analyze waiting chain و پایین ترین گزینه در نمودار درختی را EndTask کنید. اگر چیزی پیدا نکردید، نصب ویژوال استودیو را لغو کنید. 4-نصب: عدم توانایی در لغو مراحل install: راه حل این است که Task manager را باز کنید بخش Details دنبال آیتم VSinstaller باشید. روی آن کلیک راست کنید و Analyze waiting chain و پایین ترین گزینه در نمودار درختی را EndTask کنید. اگر چیزی پیدا نکردید، کل پراسس VSinstaller را EndTask کنید. 5-نصب: عدم توانایی در گرفتن برخی پکیج ها: برخی پکیج ها مانند JDK, Android SDK,NDK و برخی دیگر از پکیج ها به دلیل تحریم در دسترس نیستند. لذا برای نصب آنها نیاز به VPN داریم. 6- بعد از نصب: عدم توانایی در باز کردن ویژوال استودیو: دلیل این مشکل؛ نصب ناقص پکیج های ویژوال استودیو است. این مشکل با Rapair و Modify درست می شود. 7-بعد از نصب: مشکلات اکتیویشن: اگر ویژوال استودیو از شما کد اکتیویشن میخواهد این ها را امتحان کنید Enterprise: NJVYC-BMHX2-G77MM-4XJMR-6Q8QF Professional: KBJFW-NXHK6-W4WJM-CRMQB-G3CDH 8-هنگ و کرش در پروژه های زامارین (و بقیه ی پروژه های Third Party): دلیل این هنگ و کرش این است که ویژوال استودیو فایل های مربوطه به این پروژه ها را پیدا نمیکند. لذا بعد از Reapir و Modify و گرفتن تمامی پکیچ ها و دیپندنسی های لازم، نیاز است از نصب صحیح پکیج ها(حاوی SDK ها Runtime ها و ...) اطمینان حاصل کنیم. مشکلی که برای شخص بنده به وجود آمده بود، Android SDK و NDK در پوشه ی مخصوصش نبود که با انتقال به آن پوشه مشکل برطرف شد. 9- هنگ در کار با دیزاینر : این مشکل یکی از اذیت کننده ترین باگ های ویژوال استودیو 2017 است. اما راه حل این است که کمی صبر کنید، اگر مشکل برطرف نشد Task manager را باز کنید بخش Details دنبال آیتم DevEnvباشید. روی آن کلیک راست کنید و Analyze waiting chain و پایین ترین گزینه در نمودار درختی را EndTask کنید. نکته این است که دیزاینر کرش کرده و بلا استفاده خواهد شد. پس نیاز است آن را reload کنیم. 10-اکسپشن در ویژوال استودیو در هنگام تغییر یک پراپرتی از نوع Thickness یا استایل و تمپلیت های پیچیده در زمل به صورت لایو: سعی کنید این کار را نکنید! ولی در صورت بروز این مشکل گاها زدن دکمه ی Continue میتواند مشکل را رفع کند. اما در اکثر موارد نرم افزار کرش می کند و شما نیاز دارید اپلیکیشن را دوباره بیلد بگیرید. 11-بروز مشکل استفاده از فایل pdb آفلاین(سیمبل) در .NET Native یا Mixed دیباگ: راه حل مشخصی برای این مشکل وجود ندارد، لذا سعی کنید سیمبل های دیباگ را به صورت آنلاین دریافت کنید. 12- مشکل در گرفتن پکیج از نوگت: ابتدا لینک نوگت را از تنظیمات نوگت چک کنید. یکی ازین دو سرور باید ست شده باشد(V3 پیشنهاد می شود) https://api.nuget.org/v3/index.json https://www.nuget.org/api/v2 اگر با تصحیح سرور ها باز هم مشکل پابرجا بود، با VPN امتحان کنید.(خاموش روشن کردن مودم فراموش نشه) اگر باز هم به مشکل خوردید، VPN را باز کنید، نرم افزار Fiddler را هم باز کنید، روی WinConfig کلیک کنید، سپس روی Exempt all کلیک کنید و در نهایت Save Changes با بزنید. مشکلتان برطرف خواهد شد. 13-مشکلات ایمولیتور (بیشتر مشکلات مربوط به اندروید است) در نصب نرم افزار و یا اتصال به اینترنت: این مشکل اغلب به دلیل بروز ایراد در HyperV Vethernet به وجود می آید که با دستکاری تنظیمات HyperV قابل حل است. در این تاپیک و این تاپیک در مورد این موضوع بحث شده و راه حل هایی ارائه شده است. 14-مشکلات و ارور های عجیب و غریب هنگام بیلد: گاها پیش می آید که با وجود این که کد صحیح نوشته شده، باز هم ارور میخوریم. برای حل این مشکل شما باید ویژوال استودیو را بسته و فایل های از قبل کامپایل شده را پاک کنید. در پروژه های سی شارپ این فایل ها در پوشه های Obj و Bin اند و در پروژه های C++ معمولا در داخل پوشه های Generated files, ARM,X64,X86 اند که شما باید نسبت به پاک کردنشان اقدام کنید.اگر موفق به حذف فایل ها نشدید(خطای فایل در حال استفاده و ...) گرفتید، دستگاه را ری استارت کنید. بعد از آن پروژه را Rebuild کنید. شما در ویژوال استودیو چه مشکلاتی دارید؟ زیر همین پست مشکلاتتان را با ما در میان بگذارید
  31. 3 پسند
    سلام به وین نویسی های عزیز، امروز آموزش استفاده از دیتابیس SQlite در زامارین فرمز رو برای شما آماده کردم. این آموزش بر پایه دیتابیس آماده، درون پروژه می باشد. برای این آموزش نیاز هست که کتابخانه Sqlite-net-pcl رو در هر سه پروژه iOS,Android و UWP نصب کنید. نکته: همیشه ویژوال استودیو را با Run as Administrator باز کنید تا مشکلی برای شما در حین ساخت پروژه، بروز رسانی کتابخانه ها و... پیش نیاید. پروژه ای جدید از نوع Cross Platform App به نام WN XF Database ایجاد نمایید. (نکته: من اینجا اشتباها اومدم توی پوشه ی پروژه های ویژوال استودیو این پروژه رو ایجاد کردم. در اولین نگاه شاید بگید که این که اشکالی نداره، اما وقتی کار کنید میبیند که در پروژه اندروید هر کلاسی که اضافه میشه، عملا رنگ نوشته هاش سفید هست و کار نمیکنه که این به دلیل زیاد شدن آدرس پروژه هست، برای همین بهتر هست همیشه توی پوشه روت درایو هاتون پروژه ها رو بسازید یا حداقل درون یک پوشه درون پوشه روت درایو هاتون ایجاد کنید. من بعد از ساخت پروژه اون رو کات کردم توی درایو G پوشه Sources در کامپیوترم که این مشکل پیش نیاد.) در پنجره بعدی همانند تصویر عمل کنید، یعنی Template از نوع Blank App و UI technology از نوع Xamarin.Forms و Code Sharing strategy از نوع Shared باشه. سپس روی OK کلیک کنید، بعد از این از شما می خواد برای پروژه UWP نسخه SDK تعریف کنید که من 14393 که نسخه سالگرد هست رو انتخاب کردم. پس از ساخت پروژه، پنجره هایی که مربوط به IOS باز شدن رو ببندید. نکته: اگه با ناگت مشکل دارید، یعنی نمی توانید کتابخانه دانلود کنید، نرم افزار Fiddler4 رو دانلود و نصب کنید. پس از نصب آنرا باز کنید و روی WinConfig کلیک کنید، چنانچه از شما پیاپی سوال پرسیده شد، روی YES کلیک کنید تا پنجره ی دیگری برایتان باز شود. در پنجره باز شده روی Exempt all کلیک کنید و روی Save changes کلیک کنید و این پنجره را ببنید. از این پس هر زمانی که میخواهید از ناگت پکیج منیجر استفاده کنید، فقط برنامه Fiddler4 رو باز کنید. روی راه حل (Solution) راست کلیک کنید و روی Manage Nuget Packages for solution را انتخاب کنید. به تب Updates برید و در ابتدا Xamarin.Forms را بروز رسانی کنید، گزینه Xamarin.Forms را تیک بزنید و روی Update کلیک کنید. چنانچه بعد از نصب این قسمت زرد رنگ را دیدید روی Restart کلیک کنید تا ویژوال استودیو ریستارت شود. بعد از ریستارت بصورت خودکار پروژه شما بارگذاری خواهد شد. پس از باز شدن، دوباره به Nuget package manager را باز کنید و در تب Updates همه ی گزینه ها را تیک بزنید و روی Update کلیک کنید تا باقی کتابخانه ها هم بروز رسانی شوند. حال با تب Browse بروید و در قسمت Search این متن را تایپ کنید و اینتر بزنید: sqlite-net-pcl نکته: نسخه های متفاوتی از Sqlite در ناگت وجود دارد اما ما فقط و فقط این نسخه را می خواهیم: این کتابخانه را نصب کنید. نکته: این نسخه توسط Frank a Krueger ساخته شده و تنها نسخه ای هست که اندروید 7 به بالا بدون باگ اجرا میشود. نکته: حتما چک کنید و ببینید که این کتابخانه ها (SQLitePCLRaw) هم خودکار با این پکیج نصب شده باشند، اگر نصب نبودند حتما آنها را خودتان نصب کنیدالبته این عکس مربوط به References پروژه اندروید است. در UWP اینطوری نیست.) حال وقت آن است که دیتابیس را به پروژه اضافه کنیم، من از دیتابیسی که قبلا درون آموزش ساخت کتاب برای ویندوزفون 8.1 ساخته بودم اینجا استفاده کردم. کپی کردن دیتابیس در پروژه UWP. دیتابیس را درون روت پروژه UWP کپی کنید سپس روی آن راست کلیک کرده و روی Properties کلیک کنید. Build Action را روی Content قرار دهید و گزینه Copy to output directory را Copy Always قرار دهید کپی کردن دیتابیس درون پروژه IOS برای اضافه کردن فایل، باید آنها را در پوشه Resources پروژه IOS اضافه کنید. روی دیتابیس راست کلیک کنید و روی Properties کلیک کنید. حتما بررسی کنید که Build Action روی BundleResource و Copy to output روی Copy Always باشد: کپی کردن دیتابیس در پروژه Android در اندروید اضافه کردن فایل به پروژه بسیار جالب است. برای اضافه کردن فایل، ابتدا پوشه ای به نام Raw درون پوشه Resources ایجاد کنید و دیتابیس را درون آن اضافه کنید. روی دیتابیس راست کلیک کرده و Properties را انتخاب کنید و گزینه Build Action را روی AndroidResource و گزینه Copy to output را روی Copy Always قرار دهید. حالا چرا جالبه؟ الان بعد از اضافه کردن فایل به پوشه Raw که ایجاد کردیم، درون پروژه اندروید یک کلاس ایجاد به همین نام ایجاد شد و یک آیدی(شناسه) از نوع Integer برای این فایل ایجاد شد. مثلا برای دسترسی به این فایل درون پروژه اندروید بدین صورت عمل می کنیم: Resources.Raw.myBookDatabase حال شاید برایتان سوال پیش آید که چگونه قرار است این فایل ها را بخوانیم؟! ما باید در پروژه Shared یک اینترفیس interface ایجاد کنید و در هر پروژه به صورت جداگانه دیتابیس را بخوانیم. اینکار را ساخت Dependency می گویند. خب درون پروژه Shared ( پروژه اول درون Solution)، یک کلاس به نام IDatabaseService ایجاد نمایید: فضای نامی SQlite را به قسمت مربوطه اضافه کنید: using SQLite; خب حالا در تعریف کلاس، به جای کلمه class کلمه public interface را بنویسید. الان کدهای زیر را بنویسید: public interface IDatabaseService { SQLiteConnection GetConnection(string fileName); void CopyDatabaseToLocal(string fileName); } خب برای اونهایی که تا حالا با اینترفیس ها کار نکردن، ما اینجا یک تابع بازگشتی به نام GetConnection تعریف کردیم که SQLiteConnection رو باز گردانی خواهد کرد. تابع بعدی، تابع کپی کردن دیتابیس خواهد بود. ما در هر سه پروژه پلتفرم سه کلاس ایجاد خواهیم کرد که از این اینترفیس مشتق میشود. یک کلاس دیگر درون پروژه Shared به نام Extensions ایجاد کنید. این کلاس به صورت static خواهد بود و در واقع یک نوع Extension نویسی برای Exception ها است که قرار است ایجاد کنیم: static class Extensions { public static string Exception(this Exception ex, string starts) { var content = $"{starts} ex: {ex.Message}\r\nSource: {ex.Source}" + $"\r\nTrace: {ex.StackTrace}"; Output(content); return content; } public static void Output(object obj) { System.Diagnostics.Debug.WriteLine(Convert.ToString(obj)); } } تابع اول یک Extension است، تابع را در یک Exception که در try...catch قرار دارد فرا بخوانیم، اگر کد ما استثنا داد، خطا را در پنجره Output ویژوال نمایش خواهد داد(فقط در حالتی که پروژه روی Debug باشد.) خب در پروژه UWP یک کلاس به نام DatabaseService_UWP ایجاد کنید. فضاهای نامی زیر را به قسمت مربوطه اضافه کنید: using System; using SQLite; using Windows.Storage; using System.IO; using Xamarin.Forms; using Windows.ApplicationModel; حالا کلاس اینترفیس را مشتق کلاسی که ایجاد کردید قرار دهید، چنانچه موس را روی IDatabaseService ببرید و روی آن کلیک کنید یک مثلث زیر آن خواهد آمد که خودکار برای شما توابعی که در اینترفیس ایجاد کردیم را برای شما در این کلاس می سازد: تکه کد زیر را پاک کنید: throw new NotImplementedException(); حال کدهای زیر را درون تابع CopyDatabaseToLocal بنویسید: public async void CopyDatabaseToLocal(string fileName) { try { StorageFile storageFile = await ApplicationData.Current.LocalFolder.GetFileAsync(fileName); // injori faghat yebar file ro copy mikonim tuye local folder storageFile = null; return; } catch { } StorageFile databaseFile = await Package.Current.InstalledLocation.GetFileAsync(fileName); await databaseFile.CopyAsync(ApplicationData.Current.LocalFolder); } دیتابیس درون پروژه را به LocalFolder کپی می کنیم. نکته: درون try...catch خط آخر return نوشتیم، اینطوری زمانی که هر بار برنامه باز می شود، اگر فایل دیتابیس درون LocalFolder موجود بود، آنرا کپی نخواهد کرد. این کار برای زمانی است که کاربر بخواهد دیتابیس را بروز رسانی کند و یا آیتمی به آن اضافه کند، اینطوری دیتابیس هر بار ریست نخواهد شد. حال تابع بازگشتی GetConnection را بنویسید: public SQLiteConnection GetConnection(string fileName) { try { var path = Path.Combine(ApplicationData.Current.LocalFolder.Path, fileName); var connection = new SQLiteConnection(path); return connection; } catch (Exception ex) { ex.Exception("DatabaseService_UWP"); } return null; } این تابع کانکشنی به دیتابیس باز می کند که ما بعد از متصل شدن، می توانیم آیتم ها را دریافت کنیم یا اینکه آنها را ویرایش و یا حذف کنیم. خب الان باید تعیین کنیم که این کلاس یک Dependency می باشد. برای اینکار، بالای فضای نامی کد زیر را بنویسید: [assembly: Dependency(typeof(WN_XF_Database.UWP.DatabaseService_UWP))] یعنی اینطوری: [assembly: Dependency(typeof(WN_XF_Database.UWP.DatabaseService_UWP))] namespace WN_XF_Database.UWP { public class DatabaseService_UWP : IDatabaseService حال درون پروژه IOS نیز یک کلاس به نام DatabaseService_IOS ایجاد نمایید. فضاهای نامی زیر را به قسمت مربوطه ی آن اضافه کنید: using SQLite; using System; using System.IO; using Xamarin.Forms; و کلاس آن: [assembly: Dependency(typeof(WN_XF_Database.iOS.DatabaseService_IOS))] namespace WN_XF_Database.iOS { public class DatabaseService_IOS :IDatabaseService { public SQLiteConnection GetConnection(string fileName) { try { var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); var libraryPath = Path.Combine(documentsPath, "..", "Library"); var path = Path.Combine(libraryPath, fileName); var connection = new SQLiteConnection(path); return connection; } catch (Exception ex) { ex.Exception("DatabaseService_IOS"); } return null; } public void CopyDatabaseToLocal(string fileName) { try { var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); var libraryPath = Path.Combine(documentsPath, "..", "Library"); var path = Path.Combine(libraryPath, fileName); if (!File.Exists(path)) { // daryafte db az masire nasb shodeye barname using (var sourceStream = File.Open("./" + fileName, FileMode.Open, FileAccess.Read)) { FileStream writeStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write); ReadWriteStream(sourceStream, writeStream); } } } catch (Exception ex) { ex.Exception("DatabaseService_IOS.CopyDatabaseToLocal"); } } private void ReadWriteStream(Stream readStream, Stream writeStream) { try { int Length = 256; Byte[] buffer = new Byte[Length]; int bytesRead = readStream.Read(buffer, 0, Length); while (bytesRead > 0) { writeStream.Write(buffer, 0, bytesRead); bytesRead = readStream.Read(buffer, 0, Length); } readStream.Close(); writeStream.Close(); } catch (Exception ex) { ex.Exception("DatabaseService_IOS.ReadWriteStream"); } } } } خب کپی کردن دیتابیس از پوشه ی نصبی برنامه پوشه MyDocuments کمی در IOS و اندروید نسبت به UWP فرق داره، همانطور که در بالا می بینید یک تابع private هم برای کپی کردن آن نوشتیم. در پروژه اندروید هم کلاسی به نام DatabaseService_Android ایجاد نمایید. فضاهای نامی مورد نیاز: using SQLite; using System; using System.IO; using System.Threading.Tasks; using Xamarin.Forms; کلاس مورد نظر: [assembly: Dependency(typeof(WN_XF_Database.Droid.DatabaseService_Android))] namespace WN_XF_Database.Droid { public class DatabaseService_Android : IDatabaseService { public SQLiteConnection GetConnection(string fileName) { try { var documentspath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); var path = Path.Combine(documentspath, fileName); var connection = new SQLiteConnection(path); return connection; } catch (Exception ex) { ex.Exception("DatabaseService_Android"); } return null; } public async void CopyDatabaseToLocal(string fileName) { try { var documentspath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); var path = Path.Combine(documentspath, fileName); if (!File.Exists(path)) { var s = Android.App.Application.Context.Resources.OpenRawResource(Resource.Raw.myBookDatabase); FileStream writeStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write); ReadWriteStream(s, writeStream); } await Task.Delay(1); } catch (Exception ex) { ex.Exception("DatabaseService_Android.CopyDatabaseToLocal"); } } private void ReadWriteStream(Stream readStream, Stream writeStream) { try { int Length = 256; Byte[] buffer = new Byte[Length]; int bytesRead = readStream.Read(buffer, 0, Length); while (bytesRead > 0) { writeStream.Write(buffer, 0, bytesRead); bytesRead = readStream.Read(buffer, 0, Length); } readStream.Close(); writeStream.Close(); } catch (Exception ex) { ex.Exception("DatabaseService_Android.ReadWriteStream"); } } } } خب حالا کلاس ها را ذخیره کنید و همه ی آنها را ببندید. در پروژه Shared یک کلاس به نام Dastan ایجاد کنید. این کلاس در اصل مدل دیتابیسی که من در SQLite ساختم، می باشد. فضای نامی مورد نیاز: using SQLite; کلاس داستان: public class Dastan { [PrimaryKey, AutoIncrement] public int Id { get; set; } public string Name { get; set; } public string Story { get; set; } public override string ToString() { return Name.ToString(); } } جدول من دارای سه ستون می باشد. Id برای شناسه، Name برای نام داستان و Story برای متن داستان. کلاس App.xaml.cs را باز کنید. رشته زیر را به صورت constant ایجاد کنید. این رشته نام فایل دیتابیس ما می باشد. چرا constant؟ زیرا نمی خواهیم به اشتباه آنرا تغییر دهیم. (این مقدار فقط readonly یعنی "فقط خواندنی" در نظر گرفته میشود.) public const string DBName = "myBookDatabase.db3"; خب تابع CopyDb را در این کلاس بنویسید: private void CopyDb() { try { DependencyService.Get<IDatabaseService>().CopyDatabaseToLocal(DBName); } catch (Exception ex) { ex.Exception("App.CopyDb"); } } خب این کد شاید برای شما کمی عجیب باشد! اما اینجا فلسفه ساخت Interface و Dependency را یاد خواهید گرفت. کار تابع Get در DependencyService اینه که یک مقدار از نوع T میگیره(T می تونه هر کلاسی باشه) و با در پلتفرم های مختلف کدی که ما ایجاد کردیم رو صدا میزنه. برای مثال اگر ما پروژه UWP را Deploy کنیم، زمانی که به این کد میرسه، DependencyService میاد interfaceـی که ما به نام IDatabaseService ساختیم رو صدا میزنه، این اینترفیس بصورت عادی هیچی نیست اما چون ما کلاس هایی در سه پلتفرم ایجاد کردیم که هم از این اینترفیس مشتق شده بودند و هم به عنوان Dependency اون ها تعریف کرده بودیم، میاد برای هر پروژه اون کلاس مورد نظر در پلتفرم مورد نظر رو صدا میزنه. که در اینجا تابع CopyDatabaseToLocal را فرا میخونه و کار Copy کردن دیتابیس از فولدر نصب شده برنامه به پوشه MyDocuments رو انجام میده. به عبارتی Dependency بصورت خودکار هنگام اجرای این کد میاد اون کدی که ما در پروژه پلتفرمی خاص ایجاد کردیم رو پیدا می کنه و اون رو فرا می خونه. خب حالا درون constructorـه App بعد از فرا خوانیِ InitializeComponent کد زیر را قرار دهید: CopyDb(); یعنی: public App () { InitializeComponent(); CopyDb(); حالا خط بعدی یعنی MainPage =... را به صورت زیر بنویسید: MainPage = new NavigationPage(new MainPage()); چرا NavigationPage؟ زیرا می خواهیم صفحه های جداگانه بسازیم و آنها را باز کنیم. این کلاس را ذخیره کرده و آنرا ببندید. کلاس دیگر در پروژه Shared به نام DatabaseHelper ایجاد نمایید. فضاهای مورد نیاز: using SQLite; using System; using System.Collections.Generic; using System.Linq; using Xamarin.Forms; کلاس مورد نظر: public class DatabaseHelper { SQLiteConnection con; public DatabaseHelper() { try { con = DependencyService.Get<IDatabaseService>().GetConnection(App.DBName); } catch (Exception ex) { ex.Exception("DatabaseHelper"); } } /// <summary> /// Gereftane kole database be sorate liste /// </summary> /// <returns>Liste db ro barmigardone</returns> public IEnumerable<Dastan> Items() { return (from t in con.Table<Dastan>() select t).ToList(); } /// <summary> /// Gereftane yek dastan /// </summary> /// <param name="id">id e dastane morede nazar</param> /// <returns>dastan ro barmigardone</returns> public Dastan GetItem(int id) { return con.Table<Dastan>().FirstOrDefault(t => t.Id == id); } /// <summary> /// Hazfe yek dastan /// </summary> /// <param name="id">id e dastan</param> public void DeleteItem(int id) { con.Delete<Dastan>(id); } /// <summary> /// Ezafe kardane dastan /// </summary> /// <param name="dastan">dastan</param> public void AddItem(Dastan dastan) { con.Insert(dastan); } /// <summary> /// Beroz rasanie dastan /// </summary> /// <param name="dastan">dastan</param> public void UpdateItem(Dastan dastan) { con.Update(dastan); } } فکر نکنم کدها گنگ باشن. فقط در constructor اومدیم با استفاده از DependencyService تابع GetConnection رو صدا زدیم تا SQLiteConnection فرا خوانده بشه. حال کلاس را ذخیره کرده و آنرا ببندید. صفحه طراحی MainPage را باز نمایید و کدهای زیر را بنویسید: <?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:WN_XF_Database" x:Class="WN_XF_Database.MainPage" Title="WN Db Sample"> <StackLayout> <Label Text="Name" Margin="2"/> <Entry x:Name="txtName" Placeholder="Enter story name"/> <Label Text="Story" Margin="2"/> <Editor x:Name="txtStory" HeightRequest="300"/> <Button x:Name="btnAdd" Text="Add" Clicked="btnAdd_Clicked"/> <Button x:Name="btnShow" Text="Show items" Clicked="btnShow_Clicked"/> </StackLayout> </ContentPage> صفحه را ذخیره کنید، سپس قسمت کدنویسی این صفحه را باز کنید و کدهای دو تابع رویدادهای آن را بنویسید: private void btnAdd_Clicked(object sender, EventArgs e) { var dastan = new Dastan(); var db = new DatabaseHelper(); dastan.Name = txtName.Text; dastan.Story = txtStory.Text; db.AddItem(dastan); } private void btnShow_Clicked(object sender, EventArgs e) { Navigation.PushModalAsync(new StoriesPage()); } تابع رویداد btnAdd_Clicked برای اضافه کردن داستان جدید به دیتابیس است. تابع btnShow_Clicked هم برای باز کردن صفحه ی داستان ها می باشد. StoriesPage صفحه ی ما برای نمایش عناوین داستان ها می باشد. برای ایجاد صفحه ی جدید، روی پروژه Shared راست کلیک کنید و گزینه Add new item را انتخاب کنید. در پنجره ی باز شده، Content Page را انتخاب کنید و نام آنرا StoriesPage قرار دهید. نکته: دو نوع ContentPage وجود دارد، یکی به اسم ContentPage و دیگری به نام ContentPage C# می باشد. نوع اول را انتخاب کنید(اسم بدون C#): کدهای XAML این صفحه را بیاورید و کدهای زیر را درون آن بنویسید: <?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="WN_XF_Database.StoriesPage" Title="Stories"> <ListView x:Name="StoryListView" SeparatorVisibility="Default"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <Grid HeightRequest="60"> <Grid.GestureRecognizers> <TapGestureRecognizer x:Name="ItemTap" Tapped="ItemTap_Tapped" NumberOfTapsRequired="1"/> </Grid.GestureRecognizers> <Label Text="{Binding Name}" TextColor="Black" VerticalOptions="CenterAndExpand" HorizontalOptions="End" Margin="5"/> </Grid> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </ContentPage> صفحه را ذخیره کرده و صفحه کدنویسی آنرا باز کنید. فضاهای نامی مورد نیاز: using System; using System.Linq; using Xamarin.Forms; using Xamarin.Forms.Xaml; تابع بازنویسی شده OnAppearing را بنویسید. این تابع در اصل همان تابع Loaded در پروژه های یونیورسال میباشد! protected override void OnAppearing() { base.OnAppearing(); var db = new DatabaseHelper(); var list = db.Items(); Extensions.Output("Story count: " + list.Count()); StoryListView.ItemsSource = list; } آیتم های دیتابیس را به ItemsSourceـه ListView بایند می کنیم. تابع Tapped را برای آیتم ها می نویسیم: private void ItemTap_Tapped(object sender, EventArgs e) { try { var grid = sender as Grid; if (grid == null) return; var dastan = grid.BindingContext as Dastan; if (dastan == null) return; Navigation.PushModalAsync(new ShowStoryPage(dastan)); } catch (Exception ex) { ex.Exception("ItemTapped"); } } چون ما این تابع را برای Grid ساختیم پس sender را Cast می کنیم به Grid سپس BindingContext یا همان مدل بایندینگ را از نوع داستان Cast می کنیم. در آخر صفحه ShowStoryPage را باز می کنیم و اطلاعات را درون Constructor آن میفرستیم. صفحه ای جدید از نوع Content Page درون پروژه Shared ایجاد کنید و نام آنرا ShowStoryPage بگذارید. درون قسمت طراحی این صفحه کدهای زیر را بنویسید: <?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="WN_XF_Database.ShowStoryPage" Title="Show story"> <ContentPage.Content> <StackLayout> <Label x:Name="txtName" TextColor="Black" HorizontalOptions="End" Font="15" Margin="5"/> <ScrollView> <Label x:Name="txtStory" TextColor="Black" HorizontalOptions="End" HorizontalTextAlignment="End" Margin="10"/> </ScrollView> </StackLayout> </ContentPage.Content> </ContentPage> صفحه را ذخیره کرده و قسمت کدنویسی آنرا باز کنید. در بالای constructor خط زیر را بنویسید: public Dastan CurrentDastan; یک کپی از تابع constructor بگیرید و یک پارامتر ورودی از نوع Dastan به آن اضافه کنید. یعنی: public ShowStoryPage () { InitializeComponent (); } public ShowStoryPage(Dastan dastan) { InitializeComponent(); CurrentDastan = dastan; } حال تابع بازنویسی شده OnAppearing را بنویسید تا اطلاعاتی که بارگذاری شده، را به تکست ها اضافه کنیم: protected override void OnAppearing() { base.OnAppearing(); if (CurrentDastan != null) { txtName.Text = CurrentDastan.Name; txtStory.Text = CurrentDastan.Story; } } به همین راحتی! دانلود سورس کد نمونه منبع: وین نویس
  32. 3 پسند
    Apiای کوچیکی که من ساختم با استفاده از Asp.Net Mvc Web Api بود. اینم آموزش ساختش: توی فایل WebApiConfig تابع Register کدهای زیر را اضافه کنید: config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("multipart/form-data")); config.Formatters.FormUrlEncodedFormatter.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("multipart/form-data")); config.Formatters.XmlFormatter.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("multipart/form-data")); کلاس مورد نیاز : using System.Collections.Generic; using System.Linq; using System.Web.Http; namespace SoorenaSiteApi.Models.Helpers { public static class HeaderHelper { public static string GetHeader(ApiController controller, string key) { try { IEnumerable<string> headerValues; if (controller.Request.Headers.TryGetValues(key, out headerValues)) return headerValues.FirstOrDefault(); } catch { } return string.Empty; } } } کد کنترلر ویت: using Newtonsoft.Json; using SoorenaSiteApi.Models.Helpers; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; using System.Web.Http; namespace SoorenaSiteApi.Controllers { public class WitController : ApiController { const string defaultAccessToken = "3PLCUPJISQTSUUAV3YLXFY3D3365MUTY"; string accessToken = string.Empty; string audioType = string.Empty; [HttpPost, Route("api/wit")] public async Task<object> Upload() { if (!Request.Content.IsMimeMultipartContent()) return new WitResponseObject { Text = "UnsupportedMediaType" }; //throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); accessToken = HeaderHelper.GetHeader(this, "Authorization"); audioType = HeaderHelper.GetHeader(this, "AudioType"); var provider = new MultipartMemoryStreamProvider(); await Request.Content.ReadAsMultipartAsync(provider); WitResponseList list = new WitResponseList(); foreach (var file in provider.Contents) { var filename = file.Headers.ContentDisposition.FileName.Trim('\"'); var buffer = await file.ReadAsByteArrayAsync(); if (string.IsNullOrEmpty(audioType)) audioType = GetType(filename); var wit = await GetCL(buffer, audioType); list.Add(wit); } if (list.Any()) return list; return new WitResponseObject { Text = "ERR" }; } async Task<WitResponseObject> GetCL(byte[] buffer, string audioType) { using (HttpClient client = new HttpClient()) { //$ curl -XPOST 'https://api.wit.ai/speech?v=20160526' \ // -i -L \ // -H "Authorization: Bearer $TOKEN" \ // -H "Content-Type: audio/wav" \ // --data-binary "@sample.wav" // addresse sende stream be wit Uri targetUri = new Uri("https://api.wit.ai/speech?v=20160526"); Dictionary<string, string> headers = new Dictionary<string, string>(); headers.Add("Transfer-encoding", "chunked"); if (string.IsNullOrEmpty(accessToken)) headers.Add("Authorization", "Bearer " + defaultAccessToken); else headers.Add("Authorization", "Bearer " + accessToken); foreach (var item in headers) client.DefaultRequestHeaders.Add(item.Key, item.Value); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(audioType)); using (ByteArrayContent byteContent = new ByteArrayContent(buffer)) { byteContent.Headers.ContentType = new MediaTypeHeaderValue(audioType); HttpResponseMessage response = await client.PostAsync(targetUri, byteContent); var content = new StreamReader(await response.Content.ReadAsStreamAsync()).ReadToEnd(); var wit = JsonConvert.DeserializeObject<WitResponseObject>(content); return wit; } } } string GetType(string filename) { var extension = filename.Substring(filename.LastIndexOf(".") + 1); if (extension.ToLower() == "mp3") return "audio/mpeg3"; else return "audio/wav"; } } public class WitResponseList : List<WitResponseObject> { } public class WitResponseObject { [JsonProperty("msg_id")] public string MessageId { get; set; } [JsonProperty("_text")] public string Text { get; set; } [JsonProperty("entities")] public object Entities { get; set; } } } موفق باشید. منبع: وین نویس
  33. 3 پسند
    آموزش برنامه نویسی با Xamain.Forms قسمت پنجم : کد نویسی اختصاصی هر سیستم عامل ! (بخش دوم) همانطور که توی قسمت قبل اشاره شد زمارین از امکانی جهت کد نویسی مخصوص هر سیستم عامل پشتیبانی میکنه . توی قسمت قبل به یک نمونه بسیار ساده پرداختیم که با استفاده از اون میشد متناسب با هر سیستم عامل پیغام مناسب به کاربر نشون بدیم که یکی از ویژگی های بسیار ساده بود . اما توی این قسمت میخوایم یک مقدار حرفه ای تر با Dependency Services کار کنیم و ببینیم واقعاً کجا ها کاربرد داره . قطعاً میدونید که هر سیستم عامل یک سری api مخصوص به خودش رو داره که احتمالا هنوز توی Xamarin.Forms پیاده سازی نشده که نمونه های بسیار بسیار زیادی از این رو میشه توی پلتفرم جدید UWP مشاهده کرد . امکاناتی مثل LiveTile یا کاشی زنده یا ساده تر حتی بستن یک برنامه یا پخش یک فایل موزیک و.... در اینجا چند نمونه کد برای نمونه قرار میدم که از Dependency Services استفاده کردم . کد اول جهت بستن برنامه هست . روش استفاده از این متد هم همونطور که توی قسمت قبل اشاره شد خیلی ساده هست DependencyService.Get<ICloseApplication>().CloseApplication(); خب ابتدا از روی فرمت دستوری که بالا نوشتم مشخصه که اینترفیس مورد نیاز برای کلاس بالا خیلی ساده یک تابع به اسم CloseApplication داره بدون هیچ پارامتری : public interface ICloseApplication { void CloseApplication(); } کلاس بستن برنامه برای اندروید : [assembly:Dependency(typeof(AppCloser))] namespace GettingStarted.Droid.Classes { class AppCloser : ICloseApplication { void ICloseApplication.CloseApplication() { var activity = (Android.App.Activity)Forms.Context; activity.FinishAffinity(); } } } کلاس بستن برنامه برای IOS : [assembly:Dependency(typeof(AppCloser))] namespace GettingStarted.iOS.Classes { class AppCloser : ICloseApplication { public void CloseApplication() { Thread.CurrentThread.Abort(); } } } کلاس بستن برنامه برای UwP و ویندوز فون 8.1 به بالا : [assembly: Dependency(typeof(ClassApp))] namespace GettingStarted.UWP.Classes { class ClassApp : ICloseApplication { public void CloseApplication() { Windows.UI.Xaml.Application.Current.Exit(); } } } یک کلاس دیگه هم اینجا براتون به اشتراک میگذارم کلاس مربوط به اجرای برنامه در Main Thread هر سیستم عامل هست . نحوه استفاده از این کلاس به این شکل هست که دستورات خودتون رو داخل delegate مینویسید ، اگر هم خواستید از دستورات async استفاده کنید به مثل HttpClient یا ... کافیه قبل از delegate کلمه کلیدی async رو اضافه کنید و به صورت async delegate استفاده کنید . به این صورت امکان استفاده از دستورات async به سادگی براتون فراهم میشه . DependencyService.Get<IMainThreedRunner>().Run( /*async if needed*/ delegate { //Your Codes Here; }); برای پیاده سازی اینترفیس کلاس بالا به شکل زیر عمل میکنیم : namespace GettingStarted.Classes { public interface IMainThreedRunner { void Run(Action act); } } کلاس ویژه برای اندروید : [assembly: Dependency(typeof(MainThreedRunner))] namespace GettingStarted.Droid.Classes { class MainThreedRunner : IMainThreedRunner { public void Run(Action act) { new Activity().RunOnUiThread(() => { act.Invoke(); }); } } } کلاس ویژه IOS : [assembly: Dependency(typeof(MainThreedRunner))] namespace GettingStarted.iOS.Classes { class MainThreedRunner : IMainThreedRunner { public void Run(Action act) { UIApplication.SharedApplication.InvokeOnMainThread(delegate { act.Invoke(); }); } } } و در نهایت کلاس ویژه UWP : [assembly: Dependency(typeof(MainThreedRunner))] namespace GettingStarted.UWP.Classes { class MainThreedRunner : IMainThreedRunner { public async void Run(Action act) { await GettingStarted.UWP.MainPage.Dispatch.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, delegate { act.Invoke(); }); } } } در کد بالا به جای MainPage.Dispatcher میتوانید از Windows.UI.Xaml.Window.Current.Dispatcher نیز استفاده کنید که روش بهتری هم هستش ! به همین روش میشه هر کدی رو به میل خودمون توی سیستم عامل های مختلف اجرا کنیم و برای به اشتراک گذاشتن کد هم فقط کافیه مثل بالا اینترفیس و کلاس های مربوط به هر سیستم عامل رو منتشر کنیم . توی قسمت بعدی آموزش به سراغ Custom Renderer خواهیم رفت که کار با خود Custom Renderer مثل تلفظ اسمش یه مقدار مشکله !!! این که چه زمانی باید از Custom Renderer کرد بحثی هست که در قسمت بعدی آموزش بهش میرسیم .
  34. 3 پسند
    برنامه یونیورسال هست. نسخه دسکتاپ رو بانک داره تست می کنه و در آپدیت بعدی اضافه میشه.
  35. 3 پسند
    به نام خدا در این آموزش قصد داریم تا طراحی رابط کاربری بصورت تطبیق پذیر رو فرا بگیریم به این معنی که با تغییرات اندازه ی صفحه ی اپلیکیشن در برنامه تغییرات ظاهری مناسب ایجاد کنیم. خب ابتدا Blend For Visual Studio 2017 رو که همراه با Visual Studio روی سیستم شما نصب شده و برای طراحی اپلیکیشن بکار میره رو باز می کنیم. توجه کنید که کاری که می خواهیم انجام بدیم با Visual Studio هم میشه انجام داد اما باید به صورت دستی کد ها رو وارد کرد که برای افراد غیر حرفه ای اصلا توصیه نمیشه. سپس دیالوگ بعدی را ok کنید خب حالا از Solution Explorer صفحه ی MainPage.XAML رو باز می کنیم و کد زیر رو درونش می نویسیم در نتیجه به این ظاهر می رسیم : حال همونطور که در تصویر زیر مشاهده می کنید ابتدا یک VisualStateGroup می سازیم و نام آن را SplitViewStates می گذاریم در این گروه از State ها (وضعیت های مختلف رابط کاربری) ما می خواهیم حالت های مختلف SplitView را در اندازه های مختلف صفحه مشخص کنیم. و در گام بعدی سه State زیر را به صورتی که می بینید اضافه میکنیم (نام ها دلخواه هستند و تاثیری ندارند) وضعیت Closed را برای زمانی اضافه کردیم که Pane باید بسته باشد. وضعیت Compact برای زمانی که Pane به صورت Compact یا فشرده نمایش داده می شود. و وضعیت open برای زمانی که Pane کامل باز است. در تصویر زیر دو نکته حائز اهمیت است : دکمه ی قرمز به معنی آن است که تغییراتی که ما در Properties هر Element انجام می دهیم برای این State ضبط می شوند. علامت چشم به معنی آن است که در حال مشاهده ی این State درون XAML Designer هستیم. خب حالا میریم سر اصل مطلب! ابتدا State Open را انتخاب می کنیم (علامت قرمز کنارش نمایش داده بشه) و برای آن یک AdaptiveTrigger اضافه میکنیم AdptiveTrigger دو متغیر دارد یکی MinWindowWidth یکی MinWindowHeight که بیانگر این هستند که اگر سایز صفحه (مثلا عرض صفحه) از مقدار متغیر بیشتر شود آن Trigger اتفاق می افتد مثلا اگر MinWindowWidth =500 باشد هنگامی که صفحه از 500 عریضتر شود این تریگر رخ می دهد. حالا که تریگر اضافه شده می تونیم بیایم تغییرات دلخواهمون رو اعمال کنیم توجه داشته باشید که تغییرات رو باید از پنجره ی properties انجام بدیم نه بصورت دستی از XAML! همین کار رو برای دو State دیگر نیز بصورت زیر انجام می دهیم : نکته ی تصویر بالا اینه که ما یه بار تیک رو میزنیم و دوباره برش می داریم تا ویژوال استودیو برای ما کد رو اضافه کنه که ما میخوایم تو این state این پراپرتی false باشه! دلیل اینکه تو تصویر بالا بجای 0 عدد 1 رو گذاشتم این بود که ویژوال استودیو اگر صفر بذاریم فکر میکنه مقدار نمی خواستیم بدیم و در نتیجه تریگر رو اضافه نمی کنه بنابرین 1 گذاشتم بعدا میتونید از خود XAML برید و صفر بذارید جاش خب حالا میایم به همین صورت یک VisualStateGroup دیگه برای اون سه تا مستطیل وسط میسازیم که دو تا State داشته باشه Vertical برای صفحه های کوچک و Horizontal برای صفحه های بزرگ من کد نهایی رو قرار میدم مراحل مثل قبل میمونه فقط پراپرتی Orientation از StackPanel رو اینبار تغییر دادیم: و نتیجه نهایی پایان!
  36. 3 پسند
    سلام این کد رو امتحان کنید var updater = TileUpdateManager.CreateTileUpdaterForApplication(); updater.Clear();
  37. 2 پسند
    من مشکلات سورس رو در قالب یک پروژه جدید رفع کردم . خود سورس به اندازه کافی مستند سازی کرده با این وجود شاید کد ها خیلی پیچیده به نظر برسن... توضیحات استفاده: ابتدا باید دو دستگاه که این برنامه بر روی اونا نصبه بلوتوثشون روشن باشه و قبلا با هم pair هم شده باشند. حالا برنامه رو در دو دستگاه اجرا کنید در یکی به صفحه کلاینت و دیگری به صفحه سرور رجوع کنید ، در صفحه سرور بر روی start listening کلیک کنید و در دستگاه دیگه روی start و سپس از لیست دستگاه های یافت شده ، دستگاه دیگر رو انتخاب کرده و بر روی connect to selected device کلیک کنید ، حالا که دو دستگاه به هم متصل هستند میتونید پیام به هم ارسال کنید. توجه : ظاهرا تنها کارکتر های ASCII پشتیبانی میشه بنابراین ارسال کارکتر های فارسی باعث کرش برنامه میشه... BluetoothChat.rar
  38. 2 پسند
    جواب کل سوالاتت تو سه خط کد : MPE.Source = Windows.Media.Core.MediaSource.CreateFromUri(new Uri("http://....", UriKind.RelativeOrAbsolute)); MPE.MediaPlayer.Play(); MPE.MediaPlayer.Pause(); //MPE = MediaPlayerElement
  39. 2 پسند
    ایونت های کیبورد فقط زمانی فایر میشن که کنترل مورد نظر فوکوس شده باشه ، یه گرید به طور عادی نمیتونه فوکوس بپذیره مگر اینکه دارای بچه ای با امکان فوکوس مثل یه ListBox باشه ، شما میتونید یه کنترل مانند یه لیست باکس خالی درون گرید قرار بدید و دوباره تست کنید.
  40. 2 پسند
    این راه اگه جواب نده راهش BackgroundMediaPlayer هستش . باید یک Windows Runtime Component بسازی که به اون مسج بزنی از فورگراند اون اجرا کنی . خواه ناخواه یک مقدار پیچیده هست ذاتاً روشش . در ضمن این روش که رامتین معرفی کرده برای بیلد 14393 به بعد فقط جواب میده البته مطمئن نیستم . تو داکیومنت مایکروسافت فک کنم نوشته بود 14393 میخواد
  41. 2 پسند
    بسم الله الرحمن الرحیم سلام با تشکر فراوان از @ryco به خاطر راهنمایی و صبرشون تو این قسمت قصد دارم اموزش بدم که دقیقا کاری که با بلوتوث کردیم رو با کابل usb بکنیم،یعنی یک یا چند LED رو روشن و خاموش کنیم. حدود هشتاد نود درصدش تکراریه وسایل مورد نیاز : 1. دستگاه با قابلیت اجرای ویندوز 10 2. برد آردوئینو 3. یک LED معمولی(برای اینکه لامپتون نسوزه باید از مقاوت استفاده کنید) در اخر هم یک کابل usb برای اپلود کدمون(از همین به عنوان منبع تغذیه استفاده میشه) ویژوال استدیو رو باز میکنیم در قسمت ویندوز یونیورسال سی شارپ Blank App را انتخاب میکنیم بعد از تعیین اسم و مسیر ، صبر میکنیم تا پروژه اماده شه. از مسیر Tools > NuGet Package Manager > Manage NuGet Packages for Solution پکیج Windows Remote Arduino رو نصب میکنیم و بعد پروژه رو Rebuild کنید. پس از این کار در منوی سولوشن، روی Package.appxmanifest راست کلیک کنید و گزینه View Code رو بزنید. می خواهیم قابلیت ها (نیازها) رو معرفی کنیم. موارد زیر رو در زیر تگ <Capabilities> وارد کنید: برای اتصال با پورت سریال(USB) : <DeviceCapability Name="serialcommunication"> <Device Id="any"> <Function Type="name:serialPort"/> </Device> </DeviceCapability> حالا دوباره در کادر منوی سولوشن بر روی MainPage.xaml راست کلیک کرده و گزینه View Code رو انتخاب کنید.پایین using ها این سه تارو اضافه کنید: using Microsoft.Maker.Serial; using Microsoft.Maker.RemoteWiring; using Microsoft.Maker.Firmata; چون جناب @ryco توضیحات کامل دادند من دوباره توضیح نمیدم فقط قسمت های که لازم به تغییر هستو میگم فقط به جای این: conn = new BluetoothSerial("Dev B"); و conn.begin(57600, 0); اینو قرار بدین: conn = new UsbSerial("VID_2341","PID_0043"); و conn.begin(57600, SerialConfig.SERIAL_8N1); بقیه مراحل برنامه نویسی ویژوال مثل اموزش قبل هست فقط به یک نکنه باید توجه کرد در پرانتز UsbSerial باید اطلاعات مربوط به پورتی که اردوینو تو متصل کردین باشه که در قسمت Device Manager > Ports هست. در این قسمت بردتون رو انتخاب میکنین در تب Details قسمت Property رو روی Hardware lds تنظیم میکنیم و اطلاعاتی که تو عکس زیرش خط کشیده شده با قالبی که تو کدی که گذاشتم، داخل کدتون بزارین ------------------------------------------------------------------------------------------- خوب کارمون با ویژوال استدیو تموم شد حال میریم سراغ برد آردوینو با توضیحاتی که در پست قبل داده شده نوع برد و پورت متصل به اردوینو را تنظیم میکنیم. IDE مخصوص اردوینو رو باز میکنیم از این مسیر File > Examples > Firmata > StandardFirma را انتخاب میکنیم و اپلود میکنیم و تمام حالا پایه مثبت LED رو به پایه 5 دیجیتال متصل و پایه منفی روبه GND همه چی امادست و فقط کافیه بردتون رو به کامپیوتر متصل کنید و نرم افزاری که نوشتین رو اجرا کنید. اینم سورس پروژه اگه لازمتون شد .(فقط توجه داشته باشین قبل از اینکه این سورس رو اجرا کنید یک بار Rebuild کنید) AppArduino.zip
  42. 2 پسند
    @kamrantak شما باید یه یوزر ایجنت ایجاد کنی، موقع نویگیت کردن وب ویو به جایی که میخواید، از اون ایجنت استفاده کنید. //Desktop string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246"; //Mobile //string userAgent = "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.10586"; HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri("http://www.bing.com")); httpRequestMessage.Headers.Append("User-Agent", userAgent); WebView.NavigateWithHttpRequestMessage(httpRequestMessage); این کد ویندوز یونیورسال هست. WebView هم نام آبجکت وب ویو مورد نظرمون هست.
  43. 2 پسند
    @sab2020 اولا باید مطمئن بشی که هر دوتا پروژه ی .SQLite و .Tools رو نصب کرده باشی دوما مطمئن شو که نسخه ی Prerelease نگرفته باشی که در این صورت فکر میکنم کد مایگریشنش عوض شد. سوما مطمئن شو که توی کنسول Target Project روی همونی هست که اون دوتا نوگت رو روش نصب کردی و انتیتی و DBContext رو ست کردی. (توی مثال دوم من پروژه ی Core بود) در آخر هم اگر دیدی هیچ کدومش چاره ساز نبود کد ها رو چک کن، پاک کردن obj , bin و باز کردن با دسترسی ادمین و Rebuild رو امتحان کن. جواب نداد یه پروژه تست دیگه بساز با اون مایگریشن کن. باز هم اگه چاره ساز نبود اروری که میده رو بفرست برسی کنیم ببینیم چیه
  44. 2 پسند
    برای LockScreen Detailed Notification منتها یکم اذیت میشی، ولی یکم سرچ بیشتر کنی، برات ملموس تر میشه. دو تا راه است: 1- با استفاده از کتابخانه ی Notifications library (Microsoft.Toolkit.Uwp.Notifications): TileContent content = new TileContent() { Visual = new TileVisual() { LockDetailedStatus1 = "Meeting with Thomas", LockDetailedStatus2 = "11:00 AM - 12:30 PM", LockDetailedStatus3 = "Studio F", } }; 2- با استفاده از قالب XML : من اینجا قالبی که توی دنا استفاده کردم رو میدم، یه نگاهی بهش بنداز. اون قسمت DetailLC مربوط به لاک اسکرینه که Hint ش رو اسم اپلیکیشنم رو دادم، که میتونی عوضش کنی به هرچی که دوست داری البته میتونی اون تیکه رو جدا کنی و بزاری توی یه فایل XML دیگه که کد اضافه نداشته باشی. فکر نکنم بقیه ی کد هایی که لایو تایل ست میکنند به دردت بخورن. از اپلیکیشن Notifications Visualizer استفاده کن، قالب های جالبی داره. <?xml version="1.0" encoding="utf-8" ?> <tile> <visual branding="nameAndLogo"> <binding template="TileMedium" hint-textStacking="center"> <image src="TileMediumImageSource" placement="peek" hint-crop="circle" /> <text hint-style="base" hint-wrap="true" hint-align="center">TileMediumtext</text> <text hint-style="captionSubtle" hint-align="center">TileMediumSubText</text> </binding> <binding template="TileWide" hint-lockDetailedStatus1="DetailLC" hint-lockDetailedStatus2="Denna" > <group> <subgroup hint-weight="33"> <image src="TileWideImageSource" hint-crop="circle" /> </subgroup> <subgroup hint-textStacking="center"> <text hint-wrap="true">TileWideText</text> </subgroup> </group> </binding> <binding template="TileLarge" hint-textStacking="center"> <group> <subgroup hint-weight="1" /> <subgroup hint-weight="2"> <image src="TileLargeImageSource" hint-crop="circle" /> </subgroup> <subgroup hint-weight="1" /> </group> <text hint-style="title" hint-align="center">TileLargeText</text> <text hint-style="subtitleSubtle" hint-align="center">TileLargeSubText</text> </binding> </visual> </tile> اینم کد سی شارپش : string result = "Nothing to do today :) add something todo. "; XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(await FileIO.ReadTextAsync(await StorageFile.GetFileFromApplicationUriAsync( new Uri("ms-appx:///LiveTile.xml")))); //Set LockScreen Detail xmlDoc.LoadXml(xmlDoc.GetXml().Replace("DetailLC", result)); var tup = TileUpdateManager.CreateTileUpdaterForApplication(); tup.Update(new TileNotification(xmlDoc)); نکته: result چیزیه که میخوای نمایش بدی. نکته 2: xmldoc داریم فایل xml رو از جایی که ذخیره شده، لود میکنیم. و در ادامه هم جایگذاری هارو انجام میدیم. تا اینجا جواب سوالت رو گرفتی ! که البته میتونی با این ها بقیه ی لایو تایل هات رو هم بدین ترتیب ست کنی //Set Medium tile StorageFolder storageFolder = ApplicationData.Current.LocalFolder; //Hmmm this is where I'm looking for a picture StorageFile sampleFile = await storageFolder.GetFileAsync("avatar.jpg"); xmlDoc.LoadXml(xmlDoc.GetXml().Replace("TileMediumImageSource", sampleFile.Path )); xmlDoc.LoadXml(xmlDoc.GetXml().Replace("TileMediumtext", "Dear Orman!")); xmlDoc.LoadXml(xmlDoc.GetXml().Replace("TileMediumSubText", "Let's Do!")); //Set Wide Tile xmlDoc.LoadXml(xmlDoc.GetXml().Replace("TileWideImageSource", sampleFile.Path)); xmlDoc.LoadXml(xmlDoc.GetXml().Replace("TileWideText", result)); نکته: avatar.jpg به عکسیه روی حافظه اگه میخوای ازش استفاده کنی، به اون عکسی که میخوای نمایش بده آدرس دهی کن.
  45. 2 پسند
    @sab2020 مطمئن شو که Microsoft.EntityFrameworkCore.Tools رو توی پروژه ای که توش DbContext هست نصب کرده باشی اگر ارور خاصی میده بفرست تا نظر بدیم
  46. 2 پسند
    سلام این آموزش : https://docs.microsoft.com/en-us/windows/uwp/launch-resume/handle-file-activation این هم نمونه ای که @Ramtin گفت : Windows-universal-samples/Samples/AssociationLaunching at master · Mic...
  47. 2 پسند
    دومین تمرین کد با EFCore در پلتفرم یونیورسال: تعیین پروژه : یک سیستم ساده، که کاربر بتواند دانش آموزان را ذخیره کند. ابتدا یک پروژه ی یونیورسال ساده میسازیم. داخل سولوشن، کلیک راست زده و از منوی Add new project گزینه ی ClassLibrarty(Windows Universal) را میزنیم(من نام Core را برای آن انتخاب کردم. بعد از انجام این کار، نیاز است که پروژه ی اصلی را به پروژه ی Core رفرنس دهیم. برای این کار در پروژه ی اصلی Add reference را زده و از قسمت Projects روی Core تیک بزنید. حال این دو پکیج را از طریق کنسول نوگت یا رابط گرافیکی نوگت روی پروژه ی Core نصب میکنیم: Install-Package Microsoft.EntityFrameworkCore.Sqlite Install-Package Microsoft.EntityFrameworkCore.Tools *نکته: نیاز است که پکیج Microsoft.NETCore.UniversalWindowsPlatform نسخه ی 5.2.2 به بالا باشد. داخل پروژه ی Core می رویم، حالا کلاس های انتیتی خود را میسازیم. کلاس انتیتی چیست و چرا میسازیم؟ در جواب باید بگویم که این کلاس ها، کلاس های ساده اند که به تیبل داخل دیتابیس و در داخل کد، قالبی برای مقادیر پایگاه داده خواهند بود. کلاس اول: Teacher.cs public class Teacher { public int ID { get; set; } public string Name { get; set; } } کلاس بعدی: student.cs public class Student { public int ID { get; set; } public string Name { get; set; } //Relation to Teacher public virtual Teacher Teacher { get; set; } } هممم .... در پراپرتی Teacher چه اتفاقی افتاد؟ در جواب باید بگویم که ما یک ریلیشن (رابطه) چند به یک در اینجا داریم. نیاز است که پراپرتی مورد نظر را virtual کنیم و سپس نوع آن را از نوع تایپی که به آن ریلیشن دارد؛ انتخاب کنیم. (البته این تمام ماجرا نیست) نکته در مورد ID : انتیتی فریمورک به صورت هوشمند روی کلمه ی ID حساسیت دارد و به صورت خودکار آن را پرایمری کی تعیین کرده و آنرا Auto increment میکند. البته میشود به راحتی این تنظیمات را شخصی سازی کرد. گرچه با Fluent API و اتریبیوت [key] قابل تعیین است. کار ما با کلاس ها تمام شد! حالا یک فایل کلاس ساخته و آن را Model.cs نامگذاری میکنیم. این کلاس را از DbContext ارث بری میکنیم. نیاز است که از فضای نامی Microsoft.EntityFrameworkCore; استفاده کنیم. حالا به ازای هر کلاس انتیتی، یک DbSet میسازیم و در آخر OnConfig را اورراید میکنیم. بدین ترتیب: public class Model : DbContext { public DbSet<Student> Students { get; set; } public DbSet<Teacher> Teachers { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlite("Data Source=blogging.db"); } } حالا باید دیتابیس را مایگریت کنیم! مایگریت کردن به معنای مپ کردن کلاس ها به روی دیتابیس و یا تغییرات در آنهاست. پروژه را Rebuild کنید. اگر هنگام مایگریت کردن به مشکل خوردید، ویژوال استودیو را ببندید و با دسترسی Admin دوباره باز کنید. برای ایجاد یک مایگریشن، در Package manager این کد را بزنید: Add-Migration سپس کنسول از شما نام میخواهد، یک نام به دلخواه انتخاب کنید. بعد از آن در مسیر پروژه ی Core یک پوشه به نام Migration به وجود می آید که در آن کلاس ها و کد های مربوط به مایگریشن وجود دارد (میتوانید آن ها برسی کنید، ولی دستکاری نکنید ). حالا نیاز است که این مایگریشن، مایگریت شود. یعنی دیتابیس داخل دستگاهی که نرم افزار در آن اجرا می شود، ساخته و Map شود. اگر تغییرات وجود داشت، اعمال شود. این مایگریت در اپلیکیشن ها(مانند یونیورسال و زامارین) در ران تایم صورت میگیردو یعنی کدی مینویسیم که اگر مایگریشن اعمال نشده وجود داشت، اعمال کند. اما در انتیتی فریمورک در ASP.NET قبل از رانتایم باید مایگریت صورت بگیرد. برای مایگریت به پروژه ی اصلی بروید و در کانستراکتور App.Xaml.Cs این کد را اضاف کنید: //Core.Model is where your DbContext is located. using (var db = new Core.Model()) { db.Database.Migrate(); } *نکته: پس از هرگونه تغییر در کلاس های انتیتی، نیاز به ساخت مایگریشن جدید دارید. کار ما با ساخت و کافیگ دیتابیس تمام شد !!!! حالا برویم سراغ بقیه ی کار. کد گرفتن تمام داده های روی دیبی ست(تیبل): using (var db = new Model()) { //a gets all entities in databse. you can do what ever var a= db.Students.Include("Teacher").ToList(); } //you should add .include("Name of entity") for relations *نکته : کد .Include("Teacher") را باید بزنیم تا ارتباطات به انتیتی Teacher هم بتوانیم بگیریم. کد برای اینسرت کردن داده روی تیبل ها: using (var db = new Model()) { //std is a student object to add. better to say: var std = new student(); db.Students.Add(std); //WE should add this to confirm that we want to relate this Item to an existing one db.Entry(sdt.Teacher).State = EntityState.Unchanged; //then saves it db.SaveChanges(); } نکته: کد db.Entry(sdt.Teacher).State = EntityState.Unchanged; برای این است که تایید کنیم که آیتم Teacher یک مقدار موجود روی Teachers است. اگر این کار را نکنیم، یا انتیتی فریمورک مقدار جدید اضافه میکند و به آن لینک میکند، یا این که ارور می دهد. کد دیلیت کردن: using (var db = new Model()) { //student is an existing instance of student db.Remove(student); db.SaveChanges(); } کد دستکاری: using (var db = new Model()) { //Student is the object subject to change (Update) db.Students.Add(Student); db.Entry(Student).State = EntityState.Modified; db.Entry(Student.Teacher).State = EntityState.Unchanged; //We are about to say : Hey, EFCore! Our Student is changed, but The teacher is existing on DB. db.SaveChanges(); } *نکته : در خط db.Entry(Student).State = EntityState.Modified; ما سعی داریم به انتیتی فریمورک بگوییم که این آبجکت در دیتابیس وجود دارد و ما میخواهیم آن را تغییر دهیم. در غیر این صورت انتیتی فریمورک یک آیتم جدید به دیتابیس اینسرت می کند و به دلیل وجود آن آیتم در دیتابیس، به خطا می خوریم. * نکته: در خط db.Entry(Student.Teacher).State = EntityState.Unchanged; ما به انتیتی فریمورک میگوییم که طبق خط بالا آبجکت student عوض شده اما Teacher آن همچنان در دیبی ست(تیبل) Teachers وجود دارد. در نتیجه Teacher جدید نساز! یک کوئری ساده برای سرچ دانش آموز با ID : using (var db = new Model()) { //We want student(s) by the ID of 12 and we save it in variable a var a== db.Students.Where(x => x.ID == 12).Include("Teacher").ToList(); //Again that Include Teacher! } فایل سورس کد همین آموزش پیوست شد ! EntityCoreLearn.rar همچنین بنده قبلا یک پروژه با انتیتی فریموک کور نوشته ام که کد های آن را از این لینک میتوانید برسی کنید.
  48. 2 پسند
    نصب آفلاین شبیه ساز اندروید 6 برای Visual Studio Emulator for Android با سلام . همانطور که میدانید در نسخه های جدید ویژوال استدیو (فکر میکنم ویژوال استدیو 2015 به بعد) یک شبیه ساز اندروید به این ابزار قدرت مند اضافه شده که به شما امکان تست برنامه ها را بدون نیاز به دیوایس فیزیکی اندروید میدهد . این شبیه ساز بسیار روان ، سبک و کم حجم بوده و بدون شک به شدت با ویژوال استدیو هماهنگی دارد . در صورتیکه از این شبیه ساز ها استفاده میکنید میدانید که میتوانید پروفایل های دیگری را نیز دانلود نمائید تا از شبیه ساز های اندروید های جدید تر برای تست برنامه های خود استفاده کنید . در اینجا لینک جدید ترین پروفایل را قرار میدهم تا بدون نیاز به دانلود بتوانید از امولاتور های آن استفاده نمائید . Android M (Marshmallow / 6.0 / API 23) لینک دانلود پروفایل پس از دانلود فایل msi را اجرا کرده و منتظر پایان نصب آن بمانید . پس از نصب پروفایل در کرتانا (استارت) عبارت Visual studio emulator for android را جستجو کنید و برنامه را اجرا کنید . حال از قسمت مشخص شده پکیج دانلودی خود را انتخاب کنید یعنی Marshmallow API 23 سپس از بین شبیه ساز های موجود هر یک که میخواهید به سلیقه خود انتخاب و نصب نمائید حال بدون نیاز به دانلود امولاتور شروع به نصب خواهد نمود. نکته : بهتر است از شبیه ساز های با سایز صفحه و رزولوشن پائین تر استفاده نمائید که هم سریع تر و روان تر اجرا شود و هم به صورت پیشفرض با سایز صفحه سیستم شما هماهنگ باشد و نیاز به تغییر زوم شبیه ساز نباشد این آموزش برای اولین بار و به صورت اختصاصی در اینجا منتشر میشود ، کپی برداری از این مطلب با ذکر منبع و نویسنده بلامانع است . باتشکر
  49. 2 پسند
    با سلام دوباره، با اولین آموزش سریع پروژه محور انتیتی فریمورک کور در خدمت شما هستیم تعیین پروژه : ذخیره ی داده ها در دیتابیس با انتیتی فریمورک کور. به چه چیزی نیاز داریم ؟ -ویندوز 10 -ویژوال استودیو -آخرین ورژن ویندوز SDK پروژه ی جدید بسازید: -ویژوال استودیو را باز کنید، -File>New>Project... -از منوی C# گزینه ی Blank App (Universal Windows) را انتخاب کنید، نامی برایش تایین کنید و OK را بزنید. (من نام EFGetStarted.UWP را انتخاب کردم) Microsoft.NETCore.UniversalWindowsPlatform را به آخرین نسخه آپگرید کنید. انتیتی فریمورک کور به Microsoft.NETCore.UniversalWindowsPlatform نسخه ی 5.2.2 به بعد نیاز دارد! انتیتی فریمورک کور را نصب کنید! حال این دو پکیج را از طریق کنسول نوگت یا رابط گرافیکی نوگت روی پروژه ی Core نصب میکنیم: Install-Package Microsoft.EntityFrameworkCore.Sqlite Install-Package Microsoft.EntityFrameworkCore.Tools Model خود را بسازید! -Project ‣ Add Class... -برای کلاس جدید از نام Model.cs استفاده کنید -کد زیر را جایگزین کنید: using Microsoft.EntityFrameworkCore; using System.Collections.Generic; namespace EFGetStarted.UWP { public class BloggingContext : DbContext { public DbSet<Blog> Blogs { get; set; } public DbSet<Post> Posts { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlite("Data Source=blogging.db"); } } public class Blog { public int BlogId { get; set; } public string Url { get; set; } public List<Post> Posts { get; set; } } public class Post { public int PostId { get; set; } public string Title { get; set; } public string Content { get; set; } public int BlogId { get; set; } public Blog Blog { get; set; } } } دیتابیس خود را بسازید! داخل کنسول نوگت این کد را بزنید که اولین مایگریشن را برای شما انجام دهد : Add-Migration MyFirstMigration داخل App.XAML.cs نیز این کد را بزنید: public App() { this.InitializeComponent(); this.Suspending += OnSuspending; using (var db = new BloggingContext()) { db.Database.Migrate(); } } نیاز است این فضای نامی ها را using کنید: using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices.WindowsRuntime; از Model استفاده کنید! داخل MainPage.xaml این کد ها را وارد کنید: <Page x:Class="EFGetStarted.UWP.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:EFGetStarted.UWP" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Loaded="Page_Loaded"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <StackPanel> <TextBox Name="NewBlogUrl"></TextBox> <Button Click="Add_Click">Add</Button> <ListView Name="Blogs"> <ListView.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Url}" /> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackPanel> </Grid> </Page> و داخل MainPage.xaml.cs : public sealed partial class MainPage : Page { public MainPage() { this.InitializeComponent(); } private void Page_Loaded(object sender, RoutedEventArgs e) { using (var db = new BloggingContext()) { Blogs.ItemsSource = db.Blogs.ToList(); } } private void Add_Click(object sender, RoutedEventArgs e) { using (var db = new BloggingContext()) { var blog = new Blog { Url = NewBlogUrl.Text }; db.Blogs.Add(blog); db.SaveChanges(); Blogs.ItemsSource = db.Blogs.ToList(); } } } حالا نرم افزار را اجرا کنید تا در عمل کار را مشاهده کنید: *نکته: امکان دارد موقع اجرای اولیه ی پروژه های انتیتی فریمورک ویژوال استودیو ارور دهد، در صورت ارور، دوباره پروژه را بیلد و اجرا کنید. لینک پروژه ی همین آموزش منبع : مایکروسافت
  50. 2 پسند
    1- بله میتونید روی ایمولیتور اندروید ویژوال استودیو بریزید، ولی متاسفانه گویا بعد از هر ریلانچ ایمولیتور؛ نیازه که دوباره نصب بشه. برای این مشکل پیشنهاد میشه که از یه ایمولیتور اندروید دیگه مثلا Remix OS استفاده بشه. 2و3-ایمولیتور نباید روی بحث اینترنت مشکل داشته باشه (امکانش هست روی دیپلویمنت اپ اندروید روی ایمولیتور اندروید به مشکل بخورید که براش راه حل هست) اگه ایرادی توی زمینه ی اتصال به اینترنت پیش بیاد، احتمال فراوان از HyperV Vethernet ها است. حتما اتصالات و تنظیماتش چک بشه.
این صفحه از پرچمداران بر اساس منطقه زمانی تهران/GMT+04:30 می باشد