apeescape2.com
  • Glavni
  • Ljudje In Ekipe
  • Ui Design
  • Trendi
  • Mobilni
Back-End

ReactiveUI in vzorec MVVM v aplikacijah WPF

Reaktivno programiranje je asinhrono programska paradigma se ukvarjajo z podatkovni tokovi in širjenje sprememb. - Wikipedija

Ko preberete ta stavek, boste morda še vedno končali enako kot jaz, ko sem ga prvič prebral: Nikjer bližje razumevanju njegove pomembnosti. Še malo predanosti osnovnim konceptom in hitro boste razumeli njegov pomen. V bistvu bi si lahko o reaktivnem programiranju najprej mislili kot: »Programiranje na steroidih, ki temelji na dogodkih«. Predstavljajte si vodnik dogodkov kot tok in si oglejte vsako sprožitev vodnika kot novo referenčno točko v toku. Na kratko, kar na koncu dobite, je reaktivno programiranje.



Obstaja nekaj konceptov, ki jih boste morda želeli razumeti, preden se še malo poglobite v reaktivno programiranje. Opazovane so predmeti, ki vam omogočajo dostop do tokov, o katerih smo govorili. Njihov namen je, da vam omogočijo okno za podatke v toku. Ko se to okno odpre, lahko poglej na kakršen koli način, ki ga izberete z uporabo Operaterji na njem in se tako odločite, kdaj in kako bo vaša prijava reagira do potoka. Na koncu določite Opazovalci na nastalem toku, da določite dejanje, ki se bo zgodilo vsakič, ko tok odda novo referenčno točko.



V praksi to samo pomeni, da imate več nadzora nad načinom, kako se vaša aplikacija odziva na dogajanje, pa naj bo to vaš uporabnik, ki klikne gumb, vaša aplikacija prejme odgovor HTTP ali si opomore od izjem. Ko boste enkrat začeli videti prednosti uporabe reaktivnega programiranja (ki jih je veliko), se skoraj ne boste mogli več vrniti. To je preprosto zato, ker večina stvari, ki jih naredi aplikacija, reagira na določen način na določeno priložnost.

To zdaj še ne pomeni, da ta nov pristop nima slabih strani. Prvič, njegova krivulja učenja je lahko precej strma. Iz prve roke sem videl, kako se razvijalci (med drugim mladinci, upokojenci in arhitekti) trudijo, da bi ugotovili, kaj naj bi najprej napisali, v kakšnem vrstnem redu se izvaja njihova koda ali kako odpraviti napake. Pri prvem uvajanju teh konceptov priporočam, da pokažete veliko primerov. Ko bodo razvijalci začeli opazovati, kako naj bi stvari delovale in se uporabljale, bodo to razumeli.



Z namiznimi aplikacijami sem sodeloval več kot 10 let (večinoma Visual Basic 6, Java Swing in Windows Forms), preden sem prvič rokoval na Windows Presentation Foundation (WPF) že leta 2010. V bistvu je bil WPF ustvarjen za nadomesti Windows Forms, ki je prvi .NET-ov okvir za razvoj namizja.

Glavne razlike med WPF in Windows Forms so precejšnje, najpomembnejše pa so:

  • WPF uporablja nove razvojne paradigme, ki so močnejše in so bile temeljito preizkušene.
  • Z WPF lahko močno ločite zasnovo in kodiranje uporabniškega vmesnika.
  • WPF omogoča veliko prilagajanja in nadzora nad vašim uporabniškim vmesnikom.

Ko sem se začel učiti WPF in njegove zmožnosti, mi je bil naravnost všeč! Nisem mogel verjeti, kako enostavno je bil vzorec MVVM implementirati in kako dobro je delovala vezava lastnosti. Nisem si mislil, da bom našel kaj za izboljšanje tega načina dela, dokler nisem naletel na reaktivno programiranje in njegovo uporabo z WPF:



V tej objavi upam, da bom lahko pokazal zelo preprosto izvajanje aplikacije WPF z uporabo reaktivnega programiranja z vzorcem MVVM in dostopal do API-ja REST.

Aplikacija bo lahko:

  • Sledite avtomobilom in njihovim lokacijam
  • Vzemite informacije, pridobljene iz simuliranega vira
  • Prikažite te informacije uporabniku v nadzoru BP Maps WPF

Arhitektura

Zgradili boste odjemalca WPF, ki uporablja storitev RESTful Web API Core 2.

najboljša vadnica za c ++

Stranka:

  • WPF
  • ReactiveUI
  • Injekcija odvisnosti
  • Vzorec MVVM
  • Popravi
  • Bing Maps WPF Control
  • Samo za preizkušanje bomo uporabili Poštar

Strežniška stran:

  • .NET C # Web API Core 2
  • Injekcija odvisnosti
  • JWT overjanje

Kaj boste potrebovali:

  • Skupnost Visual Studio 2017 (ali katera koli izdaja, ki jo morda imate)

Zaledje

Hiter začetek

Zaženite novo rešitev Visual Studio s spletno aplikacijo ASP.NET Core.

wpf reactiveui: Nova spletna aplikacija ASP.NET Core Visual Studio

Konfigurirajte ga kot API, saj ga bomo uporabljali le kot zaledje za našo aplikacijo WPF.

kako določiti ceno opcije

wpf reactiveui: Konfigurirajte kot API

Na koncu bi morali dobiti rešitev VS s strukturo, podobno tej:

wpf reactiveui: Primer rešitve VS

Zaenkrat imamo vse, kar potrebujemo za zagon našega REST API-ja. Če zaženemo naš projekt, bo naložil spletni brskalnik (tistega, ki smo ga nastavili v Visual Studio), ki kaže na spletno mesto, gostovano v IIS Express, ki bo prikazalo odgovor na klic REST z objektom JSON.

Zdaj bomo za našo storitev REST nastavili JWT Authentication.

Na koncu startup.cs datoteko, dodajte naslednje vrstice.

static readonly byte[] JwtKey = Encoding.ASCII.GetBytes(@'this is a test key'); private void LoadJwtAuthorization(IServiceCollection services) { services.AddAuthentication(x => { x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(x => { x.Events = new JwtBearerEvents { OnTokenValidated = context => { var userId = int.Parse(context.Principal.Identity.Name); if (userId == 0) { //Handle user validation against DB context.Fail('Unauthorized'); } return Task.CompletedTask; } }; x.RequireHttpsMetadata = false; x.SaveToken = true; x.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(JwtKey), ValidateIssuer = false, ValidateAudience = false }; }); }

Tudi znotraj ConfigureServices , pokličite metodo, ki smo jo pravkar ustvarili pred AddMvc metoda se pokliče.

public void ConfigureServices(IServiceCollection services) { LoadJwtAuthorization(services); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }

Nazadnje prilagodite Configure metoda, tako da izgleda takole:

public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseAuthentication(); app.UseMvc(); }

Do zdaj smo vzpostavili JWT Authentication, ki se bo uporabljal na naših krmilnikih, če je ta definirana. Nato bomo prilagodili krmilnik, tako da bo uporabljal preverjanje pristnosti, ki smo ga opisali.

Na ValuesController bomo dodali AuthorizeAttribute torej spominja na to:

[Route('api/[controller]')] [ApiController] [Authorize] public class ValuesController : ControllerBase { ... }

Če bomo poskusili zagnati našo storitev, bomo dobili takšno napako 401:

Nepooblaščena napaka pri poštarju

Torej, morali bomo dodati metodo za preverjanje pristnosti naših uporabnikov. Zaradi poenostavitve bomo to storili isto ValuesController razred.

[AllowAnonymous] [HttpPost('authenticate')] public IActionResult Authenticate([FromBody]JObject userInfo) { var username = userInfo['username'].ToString(); var password = userInfo['password'].ToString(); //We would validate against the DB if (username != 'user' || password != '123') { return BadRequest(new { message = 'Username or password is incorrect' }); } // return basic user info (without password) and token to store on the front-end return Ok(CreateUserToken(1)); } private string CreateUserToken(int userId) { var tokenHandler = new JwtSecurityTokenHandler(); var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, userId.ToString()) }), Expires = DateTime.UtcNow.AddDays(7), SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(Startup.JwtKey), SecurityAlgorithms.HmacSha256Signature) }; var token = tokenHandler.CreateToken(tokenDescriptor); return tokenHandler.WriteToken(token); }

Zdaj smo ustvarili metodo z anonimnim dostopom, kar pomeni, da jo bodo lahko vsi odjemalci, tudi tisti, ki niso overjeni, poklicali s sporočilom POST, ki vsebuje objekt JSON, in predali niz za svoje uporabniško ime in niz za svoje geslo.

testno usmerjen razvoj v primerjavi z vedenjskim razvojem

Ko ga pregledamo pri poštarju, dobimo to:

WPF Reactive: Overjanje

Kot lahko vidimo, je bil rezultat metode overjanja tisti niz, ki ga moramo zdaj uporabiti kot žeton za vsak klic API-ja.

Ko je žeton vključen v glave sporočila, poteka preverjanje veljavnosti in če so posredovani pravilni parametri, storitev zažene metodo in vrne njeno vrednost. Če na primer pokličemo krmilnik vrednosti in prenesemo žeton, dobimo enak rezultat kot prej:

WPF Reactive: Authentication 2

Zdaj bomo ustvarili metodo za določanje zemljepisne širine in dolžine trenutnega avtomobila, ki mu sledimo. Še enkrat, za poenostavitev bo to zgolj preskusna metoda, ki bo najprej vrnila naključno lokacijo in začela premikati avto z določeno razdaljo vsakič, ko bo metoda poklicana.

Najprej prilagodimo Get(int id) v ValuesController razred, da bo videti tako:

[HttpGet('{id}')] public ActionResult Get(int id) { var location = LocationHelper.GetCurrentLocation(id); dynamic jsonObject = new JObject(); jsonObject.Latitude = location.latitude; jsonObject.Longitude = location.longitude; return jsonObject.ToString(); }

Nato dodamo novo LocationHelper razred, ki bo obravnaval sedanjo in prihodnjo lokacijo avtomobilov, ki jim sledimo.

public static class LocationHelper { private static readonly Random Randomizer = new Random(); private const double PositionDelta = 0.0001d; internal static (double latitude, double longitude) GetCurrentLocation(int id) { if (!Locations.ContainsKey(id)) { Locations.Add(id, default((double latitude, double longitude))); } //This method updates the last known location for the car and simulates its movement UpdateLocation(id); return Locations[id]; } private static void UpdateLocation(int id) { (double latitude, double longitude)loc = Locations[id]; //If the default value is found, randomly assign a starting point. if (loc.latitude == default(double) && loc.longitude == default(double)) { loc = Locations[id] = GetRandomStartingPoint(); } if (Randomizer.Next(2) > 0) { //In this scenario we simulate an updated latitude loc.latitude = loc.latitude + PositionDelta; } else { //Simulated longitude change loc.longitude = loc.longitude + PositionDelta; } Locations[id] = loc; } private static (double latitude, double longitude) GetRandomStartingPoint() { //Set inside the continental US return (Randomizer.Next(31, 49), Randomizer.Next(-121, -75)); } private static readonly Dictionary Locations = new Dictionary(); }

To je to za zadnji del.

Sprednji del:

Zdaj bomo ustvarili novo aplikacijo WPF. Ko smo ga ustvarili, bo Visual Studio v našo rešitev dodal nov projekt z naslednjo strukturo.

metode diskontiranih denarnih tokov za proračun kapitala osredotočajo na

Struktura aplikacije WPF

Nadzor zemljevidov Bing:

Če želimo uporabiti nadzor WPF za Bing Maps, bomo morali namestiti SDK (naveden zgoraj) in ga dodati kot sklic na našo aplikacijo WPF. Glede na to, kje ste ga namestili, je DLL morda na drugi poti. Namestil sem ga na privzeto mesto in dodal na naslednji način:

1. korak: Z desno miškino tipko kliknite razdelek Reference za svoj projekt WPF in nato kliknite

1. korak: Z desno miškino tipko kliknite razdelek Reference za svoj projekt WPF in nato kliknite »Dodaj referenco«.

2. korak: Poiščite pot do namestitve WPF Control Bing Maps.

2. korak: Poiščite pot do namestitve WPF Control Bing Maps.

3. korak: Kliknite V redu, da ga dodate v projekt.

3. korak: Kliknite V redu, da ga dodate v projekt.

Nato bomo dodali nuget pakete za reactiveui, reactiveui-wpf in refit našemu projektu WPF, ki nam bo omogočil, da bomo ustvarili modele pogledov z uporabo reaktivnega programiranja in uživanjem našega API-ja REST.

1. korak: Z desno miškino tipko kliknite odsek Reference v projektu WPF in kliknite Upravljanje paketov NuGet.

1. korak: Z desno miškino tipko kliknite odsek Reference v projektu WPF in kliknite Upravljanje paketov NuGet.

2. korak: Na zavihku Brskanje poiščite `reactiveui`, kliknite namestitev, poiščite` reactiveui-wpf`, kliknite namestitev in nazadnje poiščite `refit` in kliknite install.

2. korak: Na zavihku Brskanje poiščite `reactiveui`, kliknite namestitev, poiščite` reactiveui-wpf`, kliknite namestitev in nazadnje poiščite `refit` in kliknite install.

Zdaj bomo ustvarili svoj ViewModel. Dodajte nov razred z imenom MainViewModel.cs in naj bo videti tako:

public class MainViewModel : ReactiveObject { #region Private Members private readonly ITrackingService _service; private readonly ISubject _locationUpdate; #endregion #region Methods public MainViewModel() { _service = Locator.Current.GetService(); _locationUpdate = new Subject(); UpdateCar = ReactiveCommand.Create(() => { var parsedCorrectly = int.TryParse(NewCarToFollow, out int newCar); NewCarToFollow = null; if (!parsedCorrectly) { MessageBox.Show('There was an error reading the number of the car to follow. Please, review it.', 'Car Tracking Service', MessageBoxButton.OK, MessageBoxImage.Warning); return; } FollowedCar = newCar; }, canExecute: this.WhenAnyValue(x => x.NewCarToFollow).Select(x => !string.IsNullOrWhiteSpace(x))); /*This Scheduled method is where we get the location for the car being followed every 500 ms. We call the service with the car id, our JWT Token, and transform the result to a ValueTuple (double latitude, double longitude) to pass to our Subject's OnNext method so it can be received by the view */ Scheduler.Default.SchedulePeriodic(TimeSpan.FromMilliseconds(500), () => _service.GetLocation(FollowedCar, App.GetToken()) .Select(jo => ( latitude: double.Parse(jo['Latitude'].ToString()), longitude: double.Parse(jo['Longitude'].ToString()) )).Subscribe(newLocation => _locationUpdate.OnNext(newLocation))); } #endregion #region Properties private string _newCarToFollow; public string NewCarToFollow { get => _newCarToFollow; set => this.RaiseAndSetIfChanged(ref _newCarToFollow, value); } private int _followedCar = 1; public int FollowedCar { get => _followedCar; set => this.RaiseAndSetIfChanged(ref _followedCar, value); } public IObservable LocationUpdate => _locationUpdate; private ReactiveCommand _updateCar; public ReactiveCommand UpdateCar { get => _updateCar; set => this.RaiseAndSetIfChanged(ref _updateCar, value); } #endregion }

Če želite vedeti, da obstaja ViewModel pritrjeni nanjo in jo bomo lahko uporabljali, bomo morali spremeniti nekaj MainView.xaml.cs mapa.

public partial class MainWindow : IViewFor { public MainWindow() { InitializeComponent(); ViewModel = Locator.CurrentMutable.GetService(); /*Our ViewModel exposes an IObservable with a parameter of type ValueTuple (double latitude, double longitude) and it gets called every time the ViewModel updates the car's location from the REST API.*/ ViewModel.LocationUpdate .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(SetLocation); } private void SetLocation((double latitude, double longitude) newLocation) { //New location for the tracked vehicle. var location = new Location(newLocation.latitude, newLocation.longitude); //Remove previous pin myMap.Children.Clear(); //Center pin and keep same Zoom Level myMap.SetView(location, myMap.ZoomLevel); var pin = new Pushpin { Location = location, Background = Brushes.Green }; //Add new pin to the map myMap.Children.Add(pin); } /// /// Allows the ViewModel to be used on the XAML via a dependency property /// public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register('ViewModel', typeof(MainViewModel), typeof(MainWindow), new PropertyMetadata(default(MainViewModel))); /// /// Implementation for the IViewFor interface /// object IViewFor.ViewModel { get => ViewModel; set => ViewModel = (MainViewModel)value; } /// /// Regular property to use the ViewModel from this class /// public MainViewModel ViewModel { get => (MainViewModel)GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); } }

Nato bomo spremenili MainWindow.xaml datoteko, da bo videti tako:

Car to follow

Pomembno je prilagoditi CredentialsProvider z lastnim ključem Bing Maps.

Da bomo lahko dostopali do našega API-ja REST, bomo uporabili obnovitev. Vse, kar moramo storiti, je ustvariti vmesnik, ki opisuje metode API-jev, ki jih bomo uporabljali. Tako ustvarimo nov vmesnik z imenom ITrackingService z naslednjo vsebino:

public interface ITrackingService { [Post('/api/values/authenticate')] IObservable Authenticate([Body] JObject user); [Get('/api/values/{id}')] IObservable GetLocation(int id, [Header('Authorization')] string authorization); }

Končno spremenimo App razred za vključitev vbrizgavanja odvisnosti (z uporabo Splata, ki je bil dodan, ko smo vključili sklic na reactiveui), nastavite ServerUri (ki bi ga morali spremeniti v vrata, ki jih dobite, ko zaženete REST API) in simulirajte našo prijavo na samem začetku aplikacije.

public partial class App : Application { protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); SetDependencyInjection(); LogIn(); } private void SetDependencyInjection() { Locator.CurrentMutable.RegisterLazySingleton(() => RestService.For(ServerUri), typeof(ITrackingService)); Locator.CurrentMutable.RegisterLazySingleton(() => new MainViewModel(), typeof(MainViewModel)); } private static string Token; private const string ServerUri = 'http://localhost:54587'; private void LogIn() { try { var userInfo = new JObject { ['username'] = 'user', ['password'] = '123' }; Token = Locator.Current.GetService() .Authenticate(userInfo) .Wait(); } catch { MessageBox.Show('There was an error validating the user. Is the service up?'); Shutdown(); } } internal static string GetToken() { return $'Bearer {Token}'; } }

Na koncu, ko zaženemo našo aplikacijo, bomo lahko v realnem času videli simulacijo premikajočega se avtomobila s koordinatami, ki jih vsakih 500 ms vzamemo iz API-ja REST. Uporabnik lahko tudi avtomobil, ki ga spremljate, spremeni na kateri koli drug ID in zanj bo ustvarjen nov nabor podatkov.

Upam, da je ta majhen primer na dostopen način pokazal osnove ravnanja z API-jem REST z reaktivnim programiranjem v WPF.

Iz tega lahko vedno prenesete celoten izvorni projekt odlagališče .

Nekaj ​​področij, na katera lahko nadaljujete s tem primerom, ki vam lahko pomagajo razumeti:

najbolj priljubljena spletna mesta za zmenke 2017
  • Ustvarite prijavno okno in omogočite uporabniku prijavo in odjavo.
  • Potrdite uporabniške podatke iz baze podatkov.
  • Ustvarite različne uporabniške vloge in omejite določene metode v API-ju REST, tako da lahko do njih dostopa samo uporabnik z določeno vlogo.
  • Razumeti več reaktivnega programiranja, ki poteka skozi vse operaterje in njihovo vedenje Rx frnikole . Rx Marbles je urejena aplikacija, ki vam omogoča interakcijo s tokovi in ​​uporabo operatorjev za podatkovne točke v njih.

Zaključek

Reaktivno programiranje se lahko izkaže za koristno, če si prizadevamo doseči nadzorovan način uporabe programiranja na podlagi dogodkov, ne da bi pri tem naleteli na običajne težave, povezane s to paradigmo. Uporaba za nove dosežke je tako preprosta kot dodajanje nekaj sklicev na dobro podprte odprtokodne knjižnice. Najpomembneje pa je, da je vključitev v obstoječe zbirke kod lahko progresivna in ne sme prekiniti združljivosti s komponentami, ki je ne izvajajo. Ta članek je obravnaval reaktivno programiranje za WPF, vendar obstajajo vrata do večine glavnih jezikov in okvirov, zaradi česar je reaktivno programiranje dobra pustolovščina za vse razvijalce.

Kot vajo morate:

  • Razširite vedenje projekta z
    • Dodajanje baze podatkov za uporabnike, avtomobile in lokacije
    • Pridobivanje lokacije avtomobilov iz baze podatkov in prikaz uporabnika. Uporabniku dovolite, da raziskuje premike avtomobila v določenem časovnem obdobju
    • Dodajanje uporabniških dovoljenj. Uporabnikom skrbnikov omogočite, da ustvarjajo nove avtomobile in uporabnike in rednim uporabnikom omogočijo dostop samo za branje. Dodajte vloge v overjanje JWT.
  • Preglejte izvorno kodo za .NET reaktivne razširitve v https://github.com/dotnet/reactive

Razumevanje osnov

Kaj je JWT?

Spletni žetoni JSON so predmeti JSON, ki so varen način za predstavitev nabora informacij med obema stranema.

Zakaj uporabljati overjanje na osnovi JWT?

JWT je ena izmed najbolj priljubljenih možnosti sodobnih aplikacij za preverjanje pristnosti zaradi svoje varnosti in robustnosti.

Kakšna je korist opazovalcev?

Omogočajo enostaven način urejenega in brez večjih stroškov reševanja dogodkov in asinhronega programiranja.

Kakšne so prednosti vbrizgavanja odvisnosti?

Konstrukcijo novih predmetov lahko definirate v eni sami točki v bazi kode in od takrat naprej lahko domnevate, da bodo vaši predmeti na voljo za uporabo.

Je WPF programski jezik?

Ne. Windows Presentation Foundation je grafični podsistem Microsofta za upodabljanje uporabniških vmesnikov v aplikacijah, ki temeljijo na sistemu Windows.

Kakšna je uporaba WPF?

To je eden od načinov, na katerega lahko oblikujete namizne aplikacije za Windows. V zvezi s tem je lahko mišljena kot alternativa Windows Forms.

Je WPF vreden učenja?

WPF je Microsoftov priporočeni način za razvoj novih namiznih aplikacij. Z desetletjem stabilnosti je prilagodljiv nabor orodij, ki se uporabljajo za ustvarjanje čudovitih in sodobnih aplikacij, in omogoča enostavno ločevanje skrbi (videz in občutek vs oblikovanje), kot nobeno drugo za okolje Windows.

Oblikovanje za interaktivna okolja in pametne prostore

Ui Design

Oblikovanje za interaktivna okolja in pametne prostore
Kaj pomeni Force Touch za UI in UX?

Kaj pomeni Force Touch za UI in UX?

Mobilni

Priljubljene Objave
Uvod v odzivno spletno oblikovanje: psevdoelementi, medijske poizvedbe in še več
Uvod v odzivno spletno oblikovanje: psevdoelementi, medijske poizvedbe in še več
Idiosinkrazije za ocenjevanje biotehnologije in najboljše prakse
Idiosinkrazije za ocenjevanje biotehnologije in najboljše prakse
Poleg Crypto: Blockchain aplikacije prinašajo rešitve za podjetja
Poleg Crypto: Blockchain aplikacije prinašajo rešitve za podjetja
10 najpogostejših napak v jeziku C ++, ki jih naredijo razvijalci
10 najpogostejših napak v jeziku C ++, ki jih naredijo razvijalci
Kako implementirati iskanje T9 v iOS
Kako implementirati iskanje T9 v iOS
 
Pogled v prihodnost - trendi oblikovanja leta 2020
Pogled v prihodnost - trendi oblikovanja leta 2020
Predvidevanje: Kako ustvariti čarobne uporabniške izkušnje
Predvidevanje: Kako ustvariti čarobne uporabniške izkušnje
Obvladajte vroče trende oblikovanja s temi vajami za Photoshop
Obvladajte vroče trende oblikovanja s temi vajami za Photoshop
Pripravite se na razvijalce za Android, prihaja nov prevajalnik za Android
Pripravite se na razvijalce za Android, prihaja nov prevajalnik za Android
Optimizirana integracija programske opreme: Vadnica za Apache Camel
Optimizirana integracija programske opreme: Vadnica za Apache Camel
Priljubljene Objave
  • izkaz denarnega toka in bilanca stanja
  • kar od naslednjega ni pomembno načelo, ki ga je treba upoštevati pri prilagajanju sistema
  • kako naj vem, če mi pušča spomin
  • uporablja za rubin na tirnicah
  • datoteka .cc v primerjavi s .cpp
  • malina pi odprta vrata 8080
Kategorije
Porazdeljene Ekipe Življenjski Slog Načrtovanje In Napovedovanje Orodja In Vaje Prihodki In Rast Mobilno Oblikovanje Trendi Postopek Oblikovanja Namigi In Orodja Okretna

© 2021 | Vse Pravice Pridržane

apeescape2.com