Wie kann ich meinen Button Click so ändern, dass er immer automatisch ausgeführt wird, wenn meine TextBox nicht mehr leer ist?

1 Antwort

Vom Beitragsersteller als hilfreich ausgezeichnet

Basierend auf diesem Programm:

1) Lege dir ein neues Property im ViewModel an:

public bool NoQueriesAvailable
{
  get
  {
    return string.IsNullOrEmpty(QueryForCountry)
      && string.IsNullOrEmpty(QueryForName)
      && /* etc. ... */
  }
}

Es prüft, ob derzeit alle Textboxen leer sind oder nicht.

2) In den Setters der Properties, die den aktuellen Inhalt der jeweiligen Textboxen speichern, wird das PropertyChanged-Event getriggert. Immerhin ändert sich in diesem Moment auch der Zustand des neuen Properties.

NotifyPropertyChanged(nameof(NoQueriesAvailable));

3) Im View wird dem Button ein Style zugewiesen, welcher einen DataTrigger definiert. Dieser bindet sich an das neue Property vom ViewModel und prüft, dessen Zustand. Je nachdem kann ein anderer Text in den Button eingefügt werden.

<Button>
  <Button.Style>
    <Style TargetType="{x:Type Button}">
      <Style.Triggers>
        <DataTrigger Binding="{Binding NoQueriesAvailable}" Value="True">
          <Setter Property="Content" Value="No available" />
        </DataTrigger>
        <DataTrigger Binding="{Binding NoQueriesAvailable}" Value="False">
          <Setter Property="Content" Value="Available" />
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </Button.Style>
</Button>

4) Wenn der Button nun noch einen spezifischen Inhalt bestehend aus verschiedenen Elementen haben soll, kann man im Style noch ein Template definieren.

<Setter Property="Template">
  <Setter.Value>
    <ControlTemplate TargetType="{x:Type Button}">
      <!-- some other elements ... -->
      <TextBlock Text="{TemplateBinding Content}" />
    </ControlTemplate>
  /Setter.Value>
</Setter>

poposalat 
Beitragsersteller
 24.04.2021, 18:08

egal nicht mehr wichtig habe es jetzt so hinbekommen:

 DataTable dt = new DataTable("Person");


            dt.Columns.Add("Id", typeof(Int32));
            dt.Columns.Add("Name", typeof(string));
            dt.Columns.Add("Country", typeof(string));
            dt.Columns.Add("Location", typeof(string));
            dt.Columns.Add("Age", typeof(string));


            dt.Rows.Add(1, "Peter", "Germany", "Berlin", "18");
            dt.Rows.Add(2, "Sergej", "Bucharest", "Romania", "20");


            List<Person> personList = new List<Person>();


            for (int i = 0; i < dt.Rows.Count; i++)
            {
                Person person = new Person();
                person.Id = Convert.ToInt32(dt.Rows[i]["Id"]);
                person.Name = dt.Rows[i]["Name"].ToString();
                person.Age = dt.Rows[i]["Age"].ToString();
                person.Location = dt.Rows[i]["Location"].ToString();
                person.Country = dt.Rows[i]["Country"].ToString();


                personList.Add(person);
            }


            return personList;
0
poposalat 
Beitragsersteller
 23.04.2021, 14:38

Eine Frage zu diesem Code hab ich noch und zwar wenn ich aber aus einer DataTable jetzt die Daten in mein DataGrid Laden will wie müsste ich dann das MVVM ändern um die daten nicht aus einer Liste sondern aus einer DataTable zu laden. z.B mit dieser DataTable:

PersonsData = new DataTable()
            {
                Columns = { new DataColumn("Name", typeof(string)), new DataColumn("Age", typeof(int)), new DataColumn("Location", typeof(string)), new DataColumn("Country", typeof(string)), new DataColumn("Id", typeof(int)) }
            };
            PersonsData.Rows.Add("Peter", 11, "Berlin", "Germany", 4);
            PersonsData.Rows.Add("Pjöter", 12, "Gugelhupf", "Poland", 14);
            PersonsData.Rows.Add("Pieta", 21, "Budapest", "Czech", 40);


0
regex9  23.04.2021, 15:19
@poposalat

Direkt diese Datenquelle zu nutzen, wäre ungünstig, weil du dir damit die Filterfunktionalität komplett zerlegst. Zudem besteht keine klare Trennung zwischen Daten und Struktur.

Schreibe dir doch einfach eine Methode, die die Daten aus der DataTable zieht und in eine Liste von Personen speichert.

1
poposalat 
Beitragsersteller
 23.04.2021, 15:58
@regex9

Wo soll ich denn diese Methode schreiben in der MainWindow.xaml.cs oder in der PersonView?

0
regex9  23.04.2021, 17:53
@poposalat

Im ViewModel oder in einer Helferklasse, deren Methoden das ViewModel dann verwendet.

Nur das ViewModel bereitet die Daten für das View vor. Die xaml.cs wird für eigenen Code eigentlich gar nicht mehr genutzt. Sie beinhaltet an sich nur eine Klasse mit Konstruktor, welcher die Komponenten des View initialisiert (autogenerierter Code).

0
poposalat 
Beitragsersteller
 23.04.2021, 18:05
@regex9

Ich habe es mal so versucht in der Get Data Methode aber scheint nicht zu funktionieren:

private IList<Person> GetData()
        {
            DataTable dt = new DataTable("Student");
            dt.Columns.Add("StudentId", typeof(Int32));
            dt.Columns.Add("StudentName", typeof(string));
            dt.Columns.Add("Address", typeof(string));
            dt.Columns.Add("MobileNo", typeof(string));
            //Data  
            dt.Rows.Add(1, "Manish", "Hyderabad", "0000000000");
            dt.Rows.Add(2, "Venkat", "Hyderabad", "111111111");
            dt.Rows.Add(3, "Namit", "Pune", "1222222222");
            dt.Rows.Add(4, "Abhinav", "Bhagalpur", "3333333333");


            for (int i = 0; i < dt.Rows.Count; i++)
            {
                Person person = new Person();
                person.Age = Convert.ToInt32(dt.Rows[i]["18"]);
                person.Country = dt.Rows[i]["Germany"].ToString();
                person.Location = dt.Rows[i]["Berlin"].ToString();
                person.Name = dt.Rows[i]["Peter"].ToString();
                Person.Add(person);
            }


            return new List<Person>
            {
                new Person { Name = "Peter", Age = 11, Location = "Berlin", Country = "Germany", Id = 4 },
                new Person { Name = "Sergej", Age = 38, Location = "Bucharest", Country = "Romania", Id = 9 }
            };




        }
0
regex9  23.04.2021, 18:44
@poposalat

Es würde mich ehrlich gesagt auch wundern, wenn es das täte.

  1. Wieso müssen die Daten initial überhaupt in einer DataTable vorliegen? Ich gehe zwar davon aus, dass du dieses Objekt (am Anfang deiner Methode) bisher nur zum Test anlegst und später eigentlich von woanders holst. Doch bereits bei der tatsächlichen Quelle wäre es nicht verkehrt zu hinterfragen, wieso die Daten überhaupt je in diesem Format vorliegen müssen.
  2. Um die Spalten aus einer Row auszulesen, brauchst du den Namen der Spalte als Key. Du hingegen versuchst, den Wert, den du doch eigentlich erst ermitteln möchtest, als Key einzusetzen. Da es keine Spalte gibt, die bspw. Peter oder Berlin heißt, wirst du da keine Ergebnisse bekommen. Mehr Erfolg hättest du bspw. bei einem Key wie Address.
  3. Inwiefern sollen die Spalten der DataTable überhaupt auf die Properties der Person-Klasse übertragbar sein? Bisher hatte die Person-Klasse doch noch kein Property für eine Mobiltelefonnummer. Und im Gegenzug gibt es in der DataTable auch keine Spalte für ein Alter oder für ein Land.
  4. Du gibst eine Liste mit statisch definierten Werten zurück. In keinster Weise etwas, was du aus der DataTable herausholen würdest.
  5. Ich sehe nicht, wo du überhaupt eine Liste erzeugen würdest, in der du die ausgelesenen Daten (als Person-Objekte) speichern würdest. In deiner Schleife versuchst du stattdessen, eine Person einer Person zuzuordnen? Ich hoffe mal nicht, dass du in deiner Person-Klasse eine statische Liste definiert hast.

Die Abfolge sollte so aussehen:

Leere Liste anlegen

Durch DataRows der DataTable iterieren
  Neues Person-Objekt erstellen
  Jede Spalte der aktuellen DataRow auslesen und in passendes Property des Person-Objekts ablegen
  Person-Objekt der Liste hinzufuegen

Liste zurueckgeben

Mehr möchte ich an dieser Stelle ehrlich gesagt auch nicht mehr helfen, da das doch eher eine C#-Grundlagenübung ist. 😉

0
poposalat 
Beitragsersteller
 23.04.2021, 21:47
@regex9

Also ich habe es jetzt so gemacht:

DataTable dt = new DataTable("Person");


            dt.Columns.Add("Id", typeof(Int32));
            dt.Columns.Add("Name", typeof(string));
            dt.Columns.Add("Age", typeof(string));
            dt.Columns.Add("Location", typeof(string));
            dt.Columns.Add("Country", typeof(string));


            dt.Rows.Add(1, "Peter", "Peter", "Germany", "4", "11");
            dt.Rows.Add(2, "Sergej", "Bucharest", "Romania", "9", "38");


            List<Person> personList = new List<Person>();


            for (int i = 0; i < dt.Rows.Count; i++)
            {
                Person person = new Person();
                person.Id = Convert.ToInt32(dt.Rows[i]["Id"]);
                person.Name = dt.Rows[i]["Name"].ToString();
                person.Age = Convert.ToInt32(dt.Rows[i]["Age"]);
                person.Location = dt.Rows[i]["Location"].ToString();
                person.Location = dt.Rows[i]["Country"].ToString();


                personList.Add(person);
            }

Ich habe es nach diesem Beispiel gemacht: Beispiel

doch wie kriege ich diese Liste dann jetzt in das grid ?

0
poposalat 
Beitragsersteller
 23.04.2021, 11:07

Vergiss was ich geschrieben habe hat schon alles funktioniert, vielen Dank für dein Hilfe.

0
poposalat 
Beitragsersteller
 23.04.2021, 11:02

Hat jetzt funktioniert nur hatte ich davor es so das sobald man dann auf denn Button drückt alle TextBoxen wieder geleert werden wie müsste man das dann jetzt lösen?

0
poposalat 
Beitragsersteller
 23.04.2021, 10:37

Wie genau muss ich denn denn Xaml kram nutzen wenn ich dieses Xaml dafür als Grundlage habe?:

<TextBlock Text="&#xE71C;" x:Key="DataGridSelectAllButtonStyle.Content"/>
                <Style x:Key="{ComponentResourceKey ResourceId=DataGridSelectAllButtonStyle, TypeInTargetAssembly={x:Type DataGrid}}"
                    TargetType="{x:Type Button}">
                    <Setter Property="Background" Value="Gray"/>
                    <Setter Property="BorderBrush" Value="White"/>
                    <Setter Property="BorderThickness" Value="0 0 1 0"/>
                    <EventSetter Event="Click" Handler="ClearButton_Click"/>
                    <Setter Property="Content">
                        <Setter.Value>
                            <StackPanel Background="Gray" Height="40" Width="11">
                                <Separator Background="White" Margin="0,17,-1,0"/>
                                <TextBlock Background="{x:Null}" HorizontalAlignment="Center" Height="13"  Margin="0 5 0 0"
                            FontFamily="Segoe MDL2 Assets" FontWeight="Light" FontSize="7"
                            Text="{Binding Text, Source={StaticResource DataGridSelectAllButtonStyle.Content}}">
                                </TextBlock>
                            </StackPanel>
                        </Setter.Value>
                    </Setter>
                    
                </Style>
0