Diskuze: Nefunkčný binding v inej triede

C# .NET .NET (C# a Visual Basic) Nefunkčný binding v inej triede American English version English version

Avatar
František Pastorek:

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. října 16:17
 
Odpovědět 28. října 16:15
Avatar
ostrozan
Redaktor
Avatar
Odpovídá na František Pastorek
ostrozan:

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í
+1 bodů
Řešení problému
 
Nahoru Odpovědět  -3 29. října 11:35
Avatar
Lukas C#
Redaktor
Avatar
Odpovídá na František Pastorek
Lukas C#:

Č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  +1 29. října 12:06
Avatar
ostrozan
Redaktor
Avatar
Odpovídá na Lukas C#
ostrozan:

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. října 12:16
Avatar
Lukas C#
Redaktor
Avatar
Odpovídá na ostrozan
Lukas C#:

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  +1 29. října 12:41
Avatar
ostrozan
Redaktor
Avatar
Odpovídá na Lukas C#
ostrozan:

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. října 13:34
 
Nahoru Odpovědět 29. října 13:33
Avatar
Petr Nymsa
Redaktor
Avatar
Odpovídá na ostrozan
Petr Nymsa:
  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  +1 29. října 13:43
Pokrok nezastavíš, neusni a jdi s ním vpřed
Avatar
Jiří Gracík
Redaktor
Avatar
Odpovídá na ostrozan
Jiří Gracík:

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. října 13:53
Creating websites is awesome till you see the result in another browser ...
Avatar
Lukas C#
Redaktor
Avatar
Odpovídá na ostrozan
Lukas C#:

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. října 16:43
 
Nahoru Odpovědět 29. října 16:42
Avatar
ostrozan
Redaktor
Avatar
ostrozan:

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. října 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.