Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
František Pastorek:28.10.2016 16:15

Mením hodnotu stringu, ktorý je zmenení v inej triede ale binding sa neaktualizuje.

MainWindow.cs

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            textBox.DataContext = Log.Instance;
            Log.Instance.logContent += "aaa" + Environment.NewLine;
        }

        private void button_Click(object sender, RoutedEventArgs e)
        {
            Test.Instance.Volaj();
        }
    }

Trieda Log.cs, ktorú mám v DataContext a logConent, ktorý bindujem

class Log
    {
        public string logContent { get; set; }

        private static Log instance;
        public static Log Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new Log();
                }
                return instance;
            }
        }

        private Log()
        {  }
    }

Trieda v ktorej menim hodnotu logContent, Test.cs

class Test
    {
        private static Test instance;
        public static Test Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new Test();
                }
                return instance;
            }
        }

        private Test()
        { }

        public void Volaj()
        {
            Log.Instance.logContent += "bbb" + Environment.NewLine;
        }
    }

XAML textboxtu

<TextBox x:Name="textBox" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"  TextWrapping="Wrap" Text="{Binding logContent}" />

V textboxe mam iba aaa.

Editováno 28.10.2016 16:17
 
Odpovědět
28.10.2016 16:15
Avatar
ostrozan
Tvůrce
Avatar
Odpovídá na František Pastorek
ostrozan:29.10.2016 11:35

Máš dvě možnosti - buď by tvoje třída měla vypadat takhle:

public class Log : INotifyPropertyChanged
   {

       private static Log instance;

       public static Log Instance
       {
           get
           {
               if (instance == null)
               {
                   instance = new Log();
               }
               return instance;
           }
       }

       private Log()
       { }

       string log;

       public string logContent
       {
           get { return log; }
           set
           {
               if (log != value)
               {
                   log = value;
                   OnPropertyChanged("logContent");
               }
           }
       }

       public event PropertyChangedEventHandler PropertyChanged;
       private void OnPropertyChanged(string propertyName)
       {
           var handler = PropertyChanged;
           if (handler != null)
           {
               handler(this, new PropertyChangedEventArgs(propertyName));
           }
       }
   }

nebo pokud bude propertou nějaká kolekce tak používej ObservableCollec­tion

class Log
 {
     public ObservableCollection<string> logContent { get; set; } = new ObservableCollection<string> { "" };//tady je jen jeden prvek, ale dej si jich kolik chces

     private static Log instance;
     public static Log Instance
     {
         get
         {
             if (instance == null)
             {
                 instance = new Log();
             }
             return instance;
         }
     }

     private Log()
     { }
 }

já , protože jsem líný, tak i pro jednoduché vlastnosti používám ObservableCollec­tion s jediným prvkem :-)
jak si nelze nevšimnout - je to mnohem jednodušší

Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
 
Nahoru Odpovědět
29.10.2016 11:35
Avatar
Odpovídá na František Pastorek
Neaktivní uživatel:29.10.2016 12:06

Četl sis o Bindigu něco víc, než první odstavec na internetu? Abys mohl v kódu měnit vlastnosti, které jsou nabindované na nějaké kontrolky, potřebuješ při každé změně té vlastnoti vyvolat event PropertyChanged, který aktualizuje Bindingy na tu danou vlastnost. WPF má pro tohle interface INotifyProper­tyChanged - přečti si o něm něco. Implementace viz přísěvek nade mnou.

Nahoru Odpovědět
29.10.2016 12:06
Neaktivní uživatelský účet
Avatar
ostrozan
Tvůrce
Avatar
Odpovídá na Neaktivní uživatel
ostrozan:29.10.2016 12:16

Jestli to dobře chápu ta máš problém s použitím ObservableCollec­tion - jistě k tomu máš důvod, tak sem s ním, a´t vím co dělám špatně a proč to není vhodné?

 
Nahoru Odpovědět
29.10.2016 12:16
Avatar
Odpovídá na ostrozan
Neaktivní uživatel:29.10.2016 12:41

Tak je to Collection - trochu z toho plyne, že je určená pro ListBoxy, Comboboxy apod. ale ne pro jednotlivé property. Tak nějak na zmatení nepřítele, v tomto případě začátečníka. Chtěl bych vidět, jak s tím jako s kolekcí pracuješ, a jak vypadá Binding. Je to očividně kratší, ale že by to bylo nějak čitelné...

Nahoru Odpovědět
29.10.2016 12:41
Neaktivní uživatelský účet
Avatar
ostrozan
Tvůrce
Avatar
Odpovídá na Neaktivní uživatel
ostrozan:29.10.2016 13:33

Dík za odpověď - teď vím a se mnou každý,kdo tohle vlákno čte a bude někdy číst, že mínuska jsou za mou "lenost" - ono totiž to může svádět k tomu, že nabízená řešení nejsou správná.

Ale stejně nechápu, co je špatného na kolekci o jednom prvku - kromě toho, že její instance potřebuje víc paměti, než obyčejná proměnná - ale to snad už v dnešní době nemusíme řešit - pokud teda těch bindovaných vlastností nejsou stovky . A když jsme u toho - od kolika prvků - třeba int se kolekce (ne pole) vyplatí?

A jak stím pracuju? - Jako s prvkem kolece na indexu [0].

Text="{Binding logContent[0]}"
Editováno 29.10.2016 13:34
 
Nahoru Odpovědět
29.10.2016 13:33
Avatar
Petr Nymsa
Tvůrce
Avatar
Odpovídá na ostrozan
Petr Nymsa:29.10.2016 13:43
  1. Znepřehledňuje to kód. Taková property třeba Age. Podle názvu bych očekával, že tato property bude číselného datového typu. Rozhodně ne, že se jedná o kolekci.
  2. Navíc to porušuje myšlenku OOP. Copak, může mít třeba instance člověka, víc jak jeden věk?
  3. a nakonec, i k té paměti. Argumentovat, že v dnešní době se to nemusíš řešit je nesmysl. Extrémně ladit paměť možná ne, ale tohle je dost zásadní rozdíl.

Pro více názorností doporučuju například Clean Code: A Handbook of Agile Software Craftsmanship

-- Já dostat do ruky takovýhle kód, tak ho rovnou vyhodím.
Být potenciální zaměstanavatel a přijiít mi tam kandidát s tímto, tak pohovor končí dřív než mohl začít :)

Nahoru Odpovědět
29.10.2016 13:43
Pokrok nezastavíš, neusni a jdi s ním vpřed
Avatar
Odpovídá na ostrozan
Neaktivní uživatel:29.10.2016 13:53

Od kolika prvků se kolekce vyplatí a pole ne? Pole používáš ve vyšších jazycích pro nějaký známý a ideálně i neměnný počet prvků, kdežto kolekce v případě, že prvky potřebuješ odebírat a přidávat. A pokud jsem to nepochopil a byla to byla otázka čistě na kolekce vs vlastnost, tak samozřejmě pro jeden prvek vlastnost a pro víc kolekce/pole (ale doufám, že ses na tohle neptal). Tak jako tak mi to příjde jako tvůj zásadní nedostatek.

Nahoru Odpovědět
29.10.2016 13:53
Neaktivní uživatelský účet
Avatar
Odpovídá na ostrozan
Neaktivní uživatel:29.10.2016 16:42

Ty sám se v tom vyznáš, ale jak psali ostatní, ten kód není čistý - nestandartně použitá věc neznamená nutně originaritu a inovaci. Jestli se ti nechcou psát ty full property (nikomu se to nechce psát), tak si vytvoř utilitku, do které napíšeš datový typ a jméno Vlastnosti, a ona ti vyplivne propfull s getterem a setterem volajícím NotifyPropertyChan­ged. Je to sotva na 15 minut.

Editováno 29.10.2016 16:43
Nahoru Odpovědět
29.10.2016 16:42
Neaktivní uživatelský účet
Avatar
ostrozan
Tvůrce
Avatar
ostrozan:29.10.2016 23:12

Dík teda všem za názory - argumenty beru - člověk se pořád učí. Prostě jsem jen využil možnosti ,která se nabízela, a není to dobře.

Takže abysme se vrátili k tazateli:
upravuju svou odpověď

Implementuj do třídy rozhraní INotifyProper­tyChanged - viz výše
u kolekcí použij ObservableCollec­tion a v případě , že použiješ pouze kolekce - nemusíš rozhraní do své třídy implementovat, protože v ObservableCollec­tion je už INotifyProper­tyChanged implementované

 
Nahoru Odpovědět
29.10.2016 23:12
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 10.