• úvod
  • témata
  • události
  • tržiště
  • diskuze
  • nástěnka
  • přihlásit
    registrace
    ztracené heslo?
    TENCOKACISTROMYProgramovani v C#, F# a dalsich jazycich pro .NET, Mono a ostatni CLI implementace
    EMBI
    EMBI --- ---
    DATEL: nainstaluj si Nuget https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/ . Vsechny tyhle vetsi tam pak najdes. Staci podedit tridu. + to ma veci jako messaging, IoC, etc...

    DATEL: To by nemelo byt nutne. Do ObservableCollection si to nic neuklada. V ClassFormData mas pro kazdy combobox pro selectedvalue vlastni hodnotu?
    DATEL
    DATEL --- ---
    Ještě s dovolením znovu vypíchnu druhý dotaz, co jsem psal pod ten zdrojový kód ViewModelu, ono to tam nejspíš zapadne.

    Ohledně ItemsSource - vůbec netuším, jak to pracuje interně při bindování, ale měl jsem za to, že to je jen zdroj dat, které zobrazuje ve view. Ale nejspíš si tam nějak interně ukládá i nějaké stavy, asi v tom ObservableCollection? Protože původně jsem myslel, že mi bude stačit pro ItemsSource jen jeden ObservableCollection, který použiju pro více ComboBoxů (výběr ze seznamu studentů). Jenže se to pak chová blbě, při výběru v jiném comboboxu se zruší výběr v předchozím atd. Tj. ve výsledku musím mít pro každý ComboBox sólo ObservableCollection. Skutečně to nelze udělat jedním?
    DATEL
    DATEL --- ---
    DATEL: tak jsem už přišel na to, v čem je problém, holt žádná praxe s WPF - nedošlo mi, že jak v ClassForm.set vytvářím novou instanci FormData, tak že se to nepromítne do bindingu - tj. formulář má nabindovanou instanci FormData z konstruktoru, ale při změně instance v ClassForm.set to už formuláři nijak neřeknu, že by si to měl přebindovat. Takže stačí přidat

    OnPropertyChanged("FormData");

    do toho setteru.
    DATEL
    DATEL --- ---
    EMBI: žádné chyby právě nikde zalogované nejsou. ViewModel vypadá takto:

    public class FormDetailVM : INotifyPropertyChanged
        {
            public ObservableCollection<Student> Students { get; set; }
            public ObservableCollection<Student> Students2 { get; set; }
            public ObservableCollection<Student> Students3 { get; set; }
    
            private ClassForm classForm;
            public ClassForm ClassForm 
            { 
                get
                {
                    return classForm;
                }
                set
                {
                    classForm = value;
                    
                    if (classForm.FormData != null)
                    {
                        FormData = JsonSerializer.Deserialize<ClassFormData>(classForm.FormData);
                    }
                    else
                    {
                        FormData = new ClassFormData();
                    }
                }
            }
    
            private SchoolYearClass schoolYearClass;
            public SchoolYearClass SchoolYearClass 
            {
                get
                {
                    return schoolYearClass;
                }
                set
                {
                    schoolYearClass = value;
                    LoadStudents();
                }
            }
    
            public ClassFormData FormData { get; set; }
    
            public FormDetailVM()
            {
                Students = new ObservableCollection<Student>();
                Students2 = new ObservableCollection<Student>();
                Students3 = new ObservableCollection<Student>();
                FormData = new ClassFormData();
            }
    
            public void saveFormData()
            {
                using (var dbContext = new ApplicationDbContext())
                {
                    dbContext.ClassForms.Attach(ClassForm);
                    ClassForm.FormData = JsonSerializer.Serialize(FormData);
                    dbContext.SaveChanges();
                }
            }
    
            private void LoadStudents()
            {
                Students.Clear();
                Students2.Clear();
                Students3.Clear();
    
                using (var dbContext = new ApplicationDbContext())
                {
                    dbContext.SchoolYearClasses.Attach(schoolYearClass);
    
                    foreach (Student student in schoolYearClass.Students)
                    {
                        if (classForm.Student.Id == student.Id)
                        {
                            continue;
                        }
                        Students.Add(student);
                        Students2.Add(student);
                        Students3.Add(student);
                    }
                }
                
                OnPropertyChanged("Students");
                OnPropertyChanged("Students2");
                OnPropertyChanged("Students3");
            }
    
            public event PropertyChangedEventHandler? PropertyChanged;
    
            private void OnPropertyChanged(string propertyName)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }

    Mimochodem, rovnou položím ještě dotaz ohledně ItemsSource - vůbec netuším, jak to pracuje interně při bindování, ale měl jsem za to, že to je jen zdroj dat, které zobrazuje ve view. Ale nejspíš si tam nějak interně ukládá i nějaké stavy, asi v tom ObservableCollection? Protože původně jsem myslel, že mi bude stačit pro ItemsSource jen jeden ObservableCollection, který použiju pro více ComboBoxů (výběr ze seznamu studentů). Jenže se to pak chová blbě, při výběru v jiném comboboxu se zruší výběr v předchozím atd. Tj. ve výsledku musím mít pro každý ComboBox sólo ObservableCollection. Skutečně to nelze udělat jedním?
    EMBI
    EMBI --- ---
    DATEL: Chybu tam nevidim. Ani podle toho co pises. V debugger output ve Visual Studio nevidis binding error? Mel by tam byt, pokud je nekde problem. Pripadne nasdilej ten ViewModel.
    DATEL
    DATEL --- ---
    Zdravím, .NET a WPF není moje hlavní práce, ale teď v tom dělám jeden menší projekt a zasekl jsem se na jedné věci, ačkoli dle dostupných informací by to mělo být snad správně. Jde o použití ComboBoxu a bindování vybrané hodnoty (tj. ne celého objektu z ItemsResource). Vůbec se mi to do té property nepropisuje :(

    <ComboBox Grid.Row="1" Grid.Column="1" Height="30" Width="150" HorizontalAlignment="Left" VerticalAlignment="Top" 
       ItemsSource="{Binding Students}" DisplayMemberPath="FullName" 
       SelectedValue="{Binding FormData.Q1S1, Mode=TwoWay}" SelectedValuePath="Id" />

    Students je ObservableCollection, FormData.Q1S1 je int. Student obsahuje Id typu int. Co jsem četl, tak tak tohle by mělo fungovat, ale nejdeto. Pochopil jsem to špatně nebo jak by to mělo být správně? Díky moc za pomoc
    TOOMIX
    TOOMIX --- ---
    LARS_GUNNER
    LARS_GUNNER --- ---
    Tak bude to Blazor. Behem psani jsem narazil na to, ze by to mozna chtelo i nejake skoleni v hlubsich vecech C#. Online kurzy nebo doporucite nejaky hezky napsany projekt na Githubu, ze ktereho se da brat?
    TOOMIX
    TOOMIX --- ---
    LARS_GUNNER: Blazor
    BRAP242
    BRAP242 --- ---
    BRAP242: i kdyz spis ASP.NET
    BRAP242
    BRAP242 --- ---
    LARS_GUNNER: blazor.
    LARS_GUNNER
    LARS_GUNNER --- ---
    Budu delat webovou apku. Blog. Jeden admin ucet a data ven dostupna pres REST API. ASP.NET nebo Blazor nebo Xamarin?
    TOOMIX
    TOOMIX --- ---
    Adding color to bracket pairs - Visual Studio Blog
    https://devblogs.microsoft.com/visualstudio/adding-color-to-bracket-pairs/

    NECROMAN
    NECROMAN --- ---
    MORMEGIL: List implementuje IEnumerable interface, takže je možné ho vrátit jako IEnumerable bez konverze.
    PJOTRIK
    PJOTRIK --- ---
    Tak jasne, neni to silver bullet, ani objev ktery by prekvapil zkusenyho programatora... ale pri code review se s podobne neefektivnim kodem potkam kazdou chvili. A tenhle kanal je hlavne cileny na relativni zacatecniky nebo max prumerny developery imo
    MORMEGIL
    MORMEGIL --- ---
    NECROMAN: Tak hlavně někdy je to právě naopak: pokud tu příslušnou sekvenci umím generovat postupně (inkrementálně), tak IEnumerable mi umožní to přenést i ke konzumentovi a není pak problém zpracovat bambilion záznamů, aniž bych musel mít terabajty RAM. (Ale ano, pokud nějaká metoda vypočítá List, tak je nesmysl vracet ho jako IEnumerable.)
    NECROMAN
    NECROMAN --- ---
    NECROMAN: a ještě k té složitosti
    Immutable collection algorithmic complexity - Developer Support
    https://devblogs.microsoft.com/premier-developer/immutable-collection-algorithmic-complexity/
    NECROMAN
    NECROMAN --- ---
    NECROMAN: samozřejmě všechno je to o tom, kde to chceme použít a jak, zda primárně pro reprezentaci dat, nebo add/remove operace, nebo seek operace...

    NECROMAN
    NECROMAN --- ---
    TOOMIX: tak to hodně záleží na kontextu. Jsou situace, kdy nechceš alokovat nový List pro nějaký výsledek Linqu nebo IQueryable. Použití IEnumerable má v určitých situacích svůj význam.
    Samozřejmě moudří vědí, že při definování kontraktů a návratových hodnot je lepší používat IReadOnlyList, který konzumenta upozorní, že v kolekci, co dostane, by neměl provádět změny.
    A ještě moudřejší vědí, že existují Immutable Collections, které dají konzumentovi jistotu, že ani nikdo jiný mu pod rukama nezmění data, která dostal.
    .NET Framework - Immutable Collections | Microsoft Docs
    https://docs.microsoft.com/en-us/archive/msdn-magazine/2017/march/net-framework-immutable-collections
    SADSOUL
    SADSOUL --- ---
    Nebyl by vhodnější IReadOnlyCollection?
    TROGLODYT
    TROGLODYT --- ---
    MORMEGIL: "místo IEnumerable používat List, protože se pak při práci s tou kolekcí zbytečně neplácají zdroje na znovunačítání té kolekce"
    Kliknutím sem můžete změnit nastavení reklam