حالا میخوام ستون تشخیص هم که یه ستون از نوع string هست هم آخرین مقدار اون ستون رو بگیره.
به عنوان مثال در عکس بالا جاهایی که Highlight شده میبایست مقدار "بدهکار" داشته باشد.
آیا باز هم باید از توابع تجمعی سفارشی استفاده کنم؟
حالا میخوام ستون تشخیص هم که یه ستون از نوع string هست هم آخرین مقدار اون ستون رو بگیره.
به عنوان مثال در عکس بالا جاهایی که Highlight شده میبایست مقدار "بدهکار" داشته باشد.
آیا باز هم باید از توابع تجمعی سفارشی استفاده کنم؟
- همانطور که در تصویر مشاهده میکنید؛ آدرس پروژهی لوکال ما به شکل زیر میباشد:
http://localhost:51095/Home/Index
ngrok http [port] -host-header="localhost:[port]"
http://127.0.0.1:4040
namespace MvcApplication6.Models
{
public class Account
{
public string Name { get; set; }
public string Password { get; set; }
}
}
using System.Web.Mvc;
using MvcApplication6.Models;
namespace MvcApplication6.Controllers
{
public class LoginController : Controller
{
[HttpGet]
public ActionResult Index()
{
return View(); //Shows the login page
}
[HttpPost]
public ActionResult LoginResult()
{
string name = Request.Form["name"];
string password = Request.Form["password"];
if (name == "Vahid" && password == "123")
ViewBag.Message = "Succeeded";
else
ViewBag.Message = "Failed";
return View("Result");
}
[HttpPost]
[ActionName("LoginResultWithParams")]
public ActionResult LoginResult(string name, string password)
{
if (name == "Vahid" && password == "123")
ViewBag.Message = "Succeeded";
else
ViewBag.Message = "Failed";
return View("Result");
}
[HttpPost]
public ActionResult Login(Account account)
{
if (account.Name == "Vahid" && account.Password == "123")
ViewBag.Message = "Succeeded";
else
ViewBag.Message = "Failed";
return View("Result");
}
}
}
@model MvcApplication6.Models.Account
@{
ViewBag.Title = "Index";
}
<h2>
Login</h2>
@using (Html.BeginForm(actionName: "LoginResult", controllerName: "Login"))
{
<fieldset>
<legend>Test LoginResult()</legend>
<p>
Name: @Html.TextBoxFor(m => m.Name)</p>
<p>
Password: @Html.PasswordFor(m => m.Password)</p>
<input type="submit" value="Login" />
</fieldset>
}
@using (Html.BeginForm(actionName: "LoginResultWithParams", controllerName: "Login"))
{
<fieldset>
<legend>Test LoginResult(string name, string password)</legend>
<p>
Name: @Html.TextBoxFor(m => m.Name)</p>
<p>
Password: @Html.PasswordFor(m => m.Password)</p>
<input type="submit" value="Login" />
</fieldset>
}
@using (Html.BeginForm(actionName: "Login", controllerName: "Login"))
{
<fieldset>
<legend>Test Login(Account acc)</legend>
<p>
Name: @Html.TextBoxFor(m => m.Name)</p>
<p>
Password: @Html.PasswordFor(m => m.Password)</p>
<input type="submit" value="Login" />
</fieldset>
}
@{
ViewBag.Title = "Result";
}
<fieldset>
<legend>Login Result</legend>
<p>
@ViewBag.Message</p>
</fieldset>
<form action="/Login/LoginResult" method="post">
<fieldset>
<legend>Test LoginResult()</legend>
<p>
Name: <input id="Name" name="Name" type="text" value="" /></p>
<p>
Password: <input id="Password" name="Password" type="password" /></p>
<input type="submit" value="Login" />
</fieldset>
</form>
[AcceptVerbs(HttpVerbs.Get)]
The current request for action 'LoginResult' on controller type 'LoginController' is ambiguous between the following action methods:
System.Web.Mvc.ActionResult LoginResult() on type MvcApplication6.Controllers.LoginController
System.Web.Mvc.ActionResult LoginResult(System.String, System.String) on type MvcApplication6.Controllers.LoginController
public HttpContextBase HttpContext { get; }
public HttpRequestBase Request { get; }
public HttpResponseBase Response { get; }
public RouteData RouteData { get; }
public virtual NameValueCollection QueryString { get; } // GET variables
public NameValueCollection Form { get; } // POST variables
public HttpCookieCollection Cookies { get; }
public NameValueCollection Headers { get; }
public string HttpMethod { get; }
Request.Form
Request.QueryString
Request.Files
RouteData.Values
[HttpPost]
[ActionName("LoginResultWithFormCollection")]
public ActionResult LoginResult(FormCollection collection)
{
string name = collection["name"];
string password = collection["password"];
if (name == "Vahid" && password == "123")
ViewBag.Message = "Succeeded";
else
ViewBag.Message = "Failed";
return View("Result");
}
[HttpPost]
public ActionResult LoginResultUpdateFormCollection(FormCollection collection)
{
var account = new Account();
this.UpdateModel(account, collection.ToValueProvider());
if (account.Name == "Vahid" && account.Password == "123")
ViewBag.Message = "Succeeded";
else
ViewBag.Message = "Failed";
return View("Result");
}
[HttpPost]
public ActionResult LoginResultUpdateModel()
{
var account = new Account();
this.UpdateModel(account);
if (account.Name == "Vahid" && account.Password == "123")
ViewBag.Message = "Succeeded";
else
ViewBag.Message = "Failed";
return View("Result");
}
using System; using System.Collections.Generic; namespace MaterialAspNetCoreBackend.DomainClasses { public class User { public User() { UserNotes = new HashSet<UserNote>(); } public int Id { set; get; } public DateTimeOffset BirthDate { set; get; } public string Name { set; get; } public string Avatar { set; get; } public string Bio { set; get; } public ICollection<UserNote> UserNotes { set; get; } } }
using System; namespace MaterialAspNetCoreBackend.DomainClasses { public class UserNote { public int Id { set; get; } public DateTimeOffset Date { set; get; } public string Title { set; get; } public User User { set; get; } public int UserId { set; get; } } }
public interface IUsersService { Task<List<User>> GetAllUsersIncludeNotesAsync(); Task<User> GetUserIncludeNotesAsync(int id); }
namespace MaterialAspNetCoreBackend.WebApp.Controllers { [Route("api/[controller]")] public class UsersController : Controller { private readonly IUsersService _usersService; public UsersController(IUsersService usersService) { _usersService = usersService ?? throw new ArgumentNullException(nameof(usersService)); } [HttpGet] public async Task<IActionResult> Get() { return Ok(await _usersService.GetAllUsersIncludeNotesAsync()); } [HttpGet("{id:int}")] public async Task<IActionResult> Get(int id) { return Ok(await _usersService.GetUserIncludeNotesAsync(id)); } } }
https://localhost:5001/api/users
"build": { "builder": "@angular-devkit/build-angular:browser", "options": { "outputPath": "../MaterialAspNetCoreBackend/MaterialAspNetCoreBackend.WebApp/wwwroot",
ng build --no-delete-output-path --watch
dotnet watch run
ng g i contact-manager/models/user ng g i contact-manager/models/user-note
export interface UserNote { id: number; title: string; date: Date; userId: number; }
import { UserNote } from "./user-note"; export interface User { id: number; birthDate: Date; name: string; avatar: string; bio: string; userNotes: UserNote[]; }
ng g s contact-manager/services/user --no-spec
import { Injectable } from "@angular/core"; @Injectable({ providedIn: "root" }) export class UserService { constructor() { } }
import { HttpClient, HttpErrorResponse } from "@angular/common/http"; import { Injectable } from "@angular/core"; import { Observable, throwError } from "rxjs"; import { catchError, map } from "rxjs/operators"; import { User } from "../models/user"; @Injectable({ providedIn: "root" }) export class UserService { constructor(private http: HttpClient) { } getAllUsersIncludeNotes(): Observable<User[]> { return this.http .get<User[]>("/api/users").pipe( map(response => response || []), catchError((error: HttpErrorResponse) => throwError(error)) ); } getUserIncludeNotes(id: number): Observable<User> { return this.http .get<User>(`/api/users/${id}`).pipe( map(response => response || {} as User), catchError((error: HttpErrorResponse) => throwError(error)) ); } }
<?xml version="1.0" encoding="utf-8"?> <svg width="512" height="512" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <defs> <svg viewBox="0 0 128 128" height="100%" width="100%" pointer-events="none" display="block" id="user1" >
import { Component } from "@angular/core"; import { MatIconRegistry } from "@angular/material"; import { DomSanitizer } from "@angular/platform-browser"; @Component() export class ContactManagerAppComponent { constructor(iconRegistry: MatIconRegistry, sanitizer: DomSanitizer) { iconRegistry.addSvgIconSet(sanitizer.bypassSecurityTrustResourceUrl("assets/avatars.svg")); } }
iconRegistry.addSvgIcon( "unicorn", this.domSanitizer.bypassSecurityTrustResourceUrl("assets/unicorn_icon.svg") );
<mat-icon svgIcon="unicorn"></mat-icon>
import { User } from "../../models/user"; import { UserService } from "../../services/user.service"; @Component() export class SidenavComponent implements OnInit { users: User[] = []; constructor(private userService: UserService) { } ngOnInit() { this.userService.getAllUsersIncludeNotes() .subscribe(data => this.users = data); } }
<mat-list> <mat-list-item>Item 1</mat-list-item> <mat-list-item>Item 2</mat-list-item> <mat-list-item>Item 3</mat-list-item> </mat-list>
<mat-nav-list> <mat-list-item *ngFor="let user of users"> <a matLine href="#"> <mat-icon svgIcon="{{user.avatar}}"></mat-icon> {{ user.name }} </a> </mat-list-item> </mat-nav-list>
<mat-nav-list> <mat-list-item *ngFor="let user of users"> <a matLine [routerLink]="['/contactmanager', user.id]"> <mat-icon svgIcon="{{user.avatar}}"></mat-icon> {{ user.name }} </a> </mat-list-item> </mat-nav-list>
const routes: Routes = [ { path: "", component: ContactManagerAppComponent, children: [ { path: ":id", component: MainContentComponent }, { path: "", component: MainContentComponent } ] }, { path: "**", redirectTo: "" } ];
import { Component, OnInit } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; import { User } from "../../models/user"; import { UserService } from "../../services/user.service"; @Component({ selector: "app-main-content", templateUrl: "./main-content.component.html", styleUrls: ["./main-content.component.css"] }) export class MainContentComponent implements OnInit { user: User; constructor(private route: ActivatedRoute, private userService: UserService) { } ngOnInit() { this.route.params.subscribe(params => { this.user = null; const id = params["id"]; if (!id) { return; } this.userService.getUserIncludeNotes(id) .subscribe(data => this.user = data); }); } }
<div *ngIf="!user"> <mat-spinner></mat-spinner> </div> <div *ngIf="user"> <mat-card> <mat-card-header> <mat-icon mat-card-avatar svgIcon="{{user.avatar}}"></mat-icon> <mat-card-title> <h2>{{ user.name }}</h2> </mat-card-title> <mat-card-subtitle> Birthday {{ user.birthDate | date:'d LLLL' }} </mat-card-subtitle> </mat-card-header> <mat-card-content> <mat-tab-group> <mat-tab label="Bio"> <p> {{user.bio}} </p> </mat-tab> <!-- <mat-tab label="Notes"></mat-tab> --> </mat-tab-group> </mat-card-content> </mat-card> </div>
import { Router } from "@angular/router"; @Component() export class SidenavComponent implements OnInit, OnDestroy { users: User[] = []; constructor(private userService: UserService, private router: Router) { } ngOnInit() { this.userService.getAllUsersIncludeNotes() .subscribe(data => { this.users = data; if (data && data.length > 0 && !this.router.navigated) { this.router.navigate(["/contactmanager", data[0].id]); } }); } }
let id = params['id']; if (!id) id = 1;
<mat-sidenav #sidenav
import { MatSidenav } from "@angular/material"; @Component() export class SidenavComponent implements OnInit, OnDestroy { @ViewChild(MatSidenav) sidenav: MatSidenav;
ngOnInit() { this.router.events.subscribe(() => { if (this.isScreenSmall) { this.sidenav.close(); } }); }
smc.version = "0"
defaults write com.apple.finder AppleShowAllFiles YES
defaults write com.apple.CoreSimulator.IndigoFramebufferServices FramebufferEmulationHint 1
امکان تست بر روی بر روی آخرین نسخه iOS یعنی 12 بر روی iPhone 5s تا iPhone XS Max وجود دارد. علاوه بر این میتوانید iOS 12 را روی iPad نسل پنج و شش و iPad Air 1 و 2 و iPad Pro تست کنید. اگر قصد تست روی نسخههای قدیمیتر iOS، چون iOS 11 یا سایر دستگاهها را دارید، باید ابتدا در XCode، از منوی Window به Devices and simulators بروید و در تب Simulators روی + کلیک کنید. در قسمت OS version میتوانید نسخههای قدیمیتر را دانلود کنید یا برای Apple TV و Apple Watch نیز Simulator بسازید.
برنامه را روی iPhone 6 یا یک گوشی سبک و ساده دیگر گذاشته و برنامه را اجرا کنید و تست بگیرید. دقت کنید که Simulator روی ویندوز اجرا میشود و نیازی به سوئیچ مداوم بین ویندوز و Mac نیست. ولی اگر Simulator روی ویندوز از لحاظ UI ای عملکرد مناسبی را نداشت، در ویژوال استودیو به منوی Tools رفته و از Options > Xamarin > iOS settings تیک Remote simulator to Windows را بردارید که باعث میشود Simulator در Mac اجرا شود. در هر بار عوض کردن Simulator از گوشی ای به گوشی دیگر، پروژه را Clean - Rebuild کنید.
در سریهای بعد که ویژوال استودیو را باز میکنید، از منوی Tools > iOS گزینه Pair Mac را بزنید و به Mac خود متصل شوید.
برای اینکه بتوانید روی گوشی تست بگیرید، در همین عکس بالا، به جای iPhoneSimulator، گزینه iPhone را انتخاب کنید. بهتر است گوشی به آخرین نسخه iOS آپدیت شده باشد. همچنین iTunes for windows را نصب کنید تا ابتدا ویندوز، گوشی شما را که با کابل به کامپیوتر وصل کردهاید بشناسد. سپس در VM Ware درخواست کنید که گوشی به جای ویندوز، به Virtual Machine مک شما وصل شود. در قسمت پایین - سمت راست VM Ware برای هر سخت افزار متصل به کامپیوتر، یک گزینه هست که آنهایی که پر رنگ هستند، سخت افزارهای متصل به Virtual Mac بوده و کمرنگها را Mac نمیبیند. روی سخت افزار گوشی خود کلیک کنید و Connect را بزنید. حال باید بتوانید در iTunes موجود در Mac، اطلاعات مربوط به گوشی خود را مشاهده کنید.
به ویژوال استودیو برگشته و در قسمت Properties پروژه XamApp.iOS، به تب iOS Bundle signing رفته و ضمن انتخاب Automatic provisioning، در قسمت Team، تیم خود را انتخاب کنید. این Team را در زمان ساخت Apple Developer account ایجاد کردهاید و همانطور که قبلا در این آموزش گفته شد، اگر در ویژوال استودیو با آن لاگین کرده باشید، میتوانید آن را ببینید. در صورتی که Apple Developer account ندارید، بر اساس این آموزش پیش بروید.
زمانیکه برنامه را روی گوشی اجرا میکنید، ممکن است در Mac دیالوگ گرفتن نام کاربری و رمز عبور کاربر Mac باز شود، پس نیم نگاهی به آن داشته باشید. پس از اولین اجرای موفق روی گوشی میتوانید در XCode به منوی Window رفته و سپس Devices & simulators را باز کنید و گوشی خود را در قسمت Devices انتخاب کرده و تیک Connect via network را بزنید تا از این به بعد، بدون کابل نیز بتوانید روی گوشی خود تست کنید. البته گوشی، ویندوز و مک، باید در یک شبکه باشند.
نحوه پابلیش پروژه را در مقاله مربوط به App Center خواهیم نوشت. اما به صورت خلاصه حجم فایل ipa حدود 10 مگ است که شامل تمامی مواردی است که در قسمت Android توضیح دادیم و پروژه نهایی شما حجمی در همین حدود خواهد داشت و با اضافه کردن چندین فرم حجم اضافه نمیشود. همانطور که در قسمت توضیحات پیشرفته پروژه اندروید توضیح دادیم، اینجا نیز از AOT و LLVM برای دستیابی به بالاترین سرعت ممکن کدهای Native استفاده شده و کدهای اضافه از پروژه Link (حذف) میشوند. برای اینکار، در ویژوال استودیو iPhone - Release را انتخاب کنید و پروژه را بیلد کنید. فایل ipa درون Mac در فولدر
Library ▸ Caches ▸ Xamarin ▸ mtbs ▸ builds ▸ XamApp.iOS ▸ e9979ba2348d1c5a87390643d62c4a1b ▸ bin ▸ iPhone ▸ Release ▸ XamApp.iOS.ipa
ساخته میشود که Library فولدری در User شما بوده و مقدار Guid مربوطه، Random است. همچنین XamApp.iOS نام پروژه است.
حالتهای متصور برای عکس بالا عبارتند از [Debug - iPhoneSimulator] و [Debug - iPhone] و [Release - iPhone] که دو تای اول برای تست روی Simulator و Device بوده و حالت سوم برای Release کردن فایل ipa. طبیعی است که تنظیم [Release - Simulator] معنی نمیدهد.
با توجه به اینکه محیط توسعه برنامه را آماده کردهایم، از قسمت بعد، به آموزش کدنویسی خواهیم پرداخت.
Get .crx Chrome Extension file and extract source code in one click
نیاز نیست این افزونه را نصب کنید، فقط با Copy / Paste آدرس افزونهٔ مورد نظر از Chrome Web Store در این وب سایت، به سورسکد افزونهٔ مد نظر دسترسی پیدا خواهید کرد.