WPF Jak utworzyć trigger sprawdzający wartość bool z klasy będącej elementem DataGrida?

0

Każdy item DataGrida to klasa, posiadająca wartość bool. Chcę, aby wszystkie itemy mające wartość bool miały inne tło. Udało mi się odczytać zaznaczenie elementu, ale nie wiem jak dobrać sie do wnętrza klasy. Macie pomysł?

<DataGrid.CellStyle>
                <Style TargetType="DataGridCell">
                    <Style.Triggers> <!--Zaznaczenie-->
                        <Trigger Property="IsSelected"
                        Value="True">
                            <Setter Property="Background" >
                                <Setter.Value>
                                    <RadialGradientBrush>
                                        <GradientStop Color="#FF7EC13B" Offset="0.159"/>
                                        <GradientStop Color="#7FD1D8D5" Offset="1"/>
                                    </RadialGradientBrush>
                                </Setter.Value>
                            </Setter>
                            <Setter Property="Foreground" Value="Black" />
                        </Trigger>
                        
                    </Style.Triggers>
                </Style>
            </DataGrid.CellStyle> 
0

Nakminiłem coś takiego ale nie działa :(

<DataTrigger Binding="{Binding Path=IsPlaying}" Value="True"> <!--IsPlayed-->
                            <Setter Property="Background" >
                                <Setter.Value>
                                    <RadialGradientBrush>
                                        <GradientStop Color="AntiqueWhite" Offset="0.159"/>
                                        <GradientStop Color="Aqua" Offset="1"/>
                                    </RadialGradientBrush>
                                </Setter.Value>
                            </Setter>
                            <Setter Property="Foreground" Value="Black" />
                        </DataTrigger> 
1

Musisz wypełniać DataGrid'a odpowiednią klasą. Oprócz zwykłych pól klasa taka przechowuje również informacje na temat koloru wiersza i na temat tego czy wiersz został zaznaczony czy nie. To może być coś takiego jak poniżej:

    public class AppUser : INotifyPropertyChanged
    {
        public int No { get; set; }
        public int Id { get; set; }
        public string Username { get; set; }
        public string Name { get; set; }
        public string Surname { get; set; }

        private bool isChecked { get; set; }
        public bool IsChecked
        {
            get { return this.isChecked; }
            set
            {
                this.isChecked = value;
                this.OnPropertyChanged(nameof(this.IsChecked));

                //  Magia tutaj.
                if (this.isChecked) this.Color = "LightBlue";
                else this.Color = "White";
            }
        }

        private string color;
        public string Color
        {
            get { return this.color; }
            set
            {
                this.color = value;
                this.OnPropertyChanged(nameof(this.Color));
            }
        }

        public AppUser()
        {
            //  Musisz zdefiniować domyślny kolor w konstruktorze.
            this.Color = "White";
        }

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

Sama siatka natomiast niech wygląda tak:

    <DataGrid Grid.Row="0" Grid.Column="0" AutoGenerateColumns="False"
              HorizontalGridLinesBrush="Silver" VerticalGridLinesBrush="Silver"
              CanUserAddRows="False" HeadersVisibility="Column"
              SelectionMode="Single" SelectionUnit="FullRow"
              ItemsSource="{Binding Users,UpdateSourceTrigger=PropertyChanged,IsAsync=True}">
      <DataGrid.RowStyle>
        <Style TargetType="DataGridRow">
          <Setter Property="Background" Value="{Binding Color,UpdateSourceTrigger=PropertyChanged}"/>
        </Style>
      </DataGrid.RowStyle>
      <DataGrid.Columns>
        <DataGridTemplateColumn Header="No" SortMemberPath="No"
                                Width="auto">
          <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
              <Label Content="{Binding No}"
                     VerticalAlignment="Center"/>
            </DataTemplate>
          </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Check" SortMemberPath="IsChecked"
                                Width="auto">
          <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
              <CheckBox IsChecked="{Binding IsChecked,UpdateSourceTrigger=PropertyChanged}"
                        VerticalAlignment="Center" HorizontalAlignment="Center"/>
            </DataTemplate>
          </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Username" SortMemberPath="Username"
                                Width="*">
          <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
              <Label Content="{Binding Username}"
                     VerticalAlignment="Center"/>
            </DataTemplate>
          </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Name" SortMemberPath="Name"
                                Width="*">
          <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
              <Label Content="{Binding Name}"
                     VerticalAlignment="Center"/>
            </DataTemplate>
          </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Surname" SortMemberPath="Surname"
                                Width="*">
          <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
              <Label Content="{Binding Surname}"
                     VerticalAlignment="Center"/>
            </DataTemplate>
          </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
      </DataGrid.Columns>
    </DataGrid>

Bindowanie jest robione standardowo i wszystko samo działa.

0

A dobra, już wiem... nie zauważyłem. Zdarzenie PropertyChanged służy do powiadomienia, że własność się zmieniła ale żeby zdarzenie zadziałało to trzeba je wywołać "na rzecz" obiektu, który się zmienia i do tego jest OnPropertyChanged

Dokładniej: Zdarzenie to służy do powiadomienia widoku o tym, że wartość obiektu, a konkretnie właśność Property, się zmieniła wewnątrz DataContext'u i konieczna jest aktualizacja w widoku.

0

Orientujesz się może, dlaczego nie wyświetla mi bitmapy? Sprawdziłem zawartość stringa i pokazuje "PlayListImagePlay.bmp"
d8cf2bcc0e.png

public class PlayListTrackData : INotifyPropertyChanged
    {
        public enum eTrackStatus
        {
            ready,
            play,
            error,
            next,
        }
        public PlayListTrackData(string Path)
        {
            this.Name = "abecadło";
            this.Time = "11:12";
            TrackStatus = eTrackStatus.play;
        }
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string propertyName)
        {
            var handler = this.PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }

        private eTrackStatus trackStatus { get; set; }
        public eTrackStatus TrackStatus
        {
            get { return this.trackStatus; }
            set
            {
                this.trackStatus = value;
                if (this.trackStatus == eTrackStatus.ready)
                    IconName = "PlayListBitmapReady" + ".bmp";
                if (this.trackStatus == eTrackStatus.play)
                    IconName = "PlayListBitmapPlay" + ".bmp";
                if (this.trackStatus == eTrackStatus.error)
                    IconName = "PlayListBitmapError" + ".bmp";
                if (this.trackStatus == eTrackStatus.next)
                    IconName = "PlayListBitmapNext" + ".bmp";
                this.OnPropertyChanged("IconName");
            }
        }
        private string IconName { get; set; }
        public string Name { get; private set; }
        public string Time { get; private set; }

        public string Path { get; private set; }



    } 
1

Orientujesz się może, dlaczego nie wyświetla mi bitmapy?

No generalnie orientuję się. Należy po prostu skorzystać z Resource file, a nie na ślepo dodawać obrazki do drzewa.

0
private eTrackStatus trackStatus { get; set; }
        public eTrackStatus TrackStatus
        {
            get { return this.trackStatus; }
            set
            {
                this.trackStatus = value;
                if (this.trackStatus == eTrackStatus.ready)
                    IconName = "Ready16" + ".png";
                if (this.trackStatus == eTrackStatus.play)
                    IconName = "Play16" + ".png";
                if (this.trackStatus == eTrackStatus.error)
                    IconName = "Error16" + ".png";
                if (this.trackStatus == eTrackStatus.next)
                    IconName = "Next16" + ".png";
                this.OnPropertyChanged("IconName");
            }
        }
        private string IconName { get; set; } 

213880c9c9.png

            <DataGrid.Columns>
                <!--definicje kolumn-->
                <DataGridTemplateColumn Header=" " CanUserResize="False" MaxWidth="16" MinWidth="16">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Image Source="{Binding Path=IconName}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTextColumn Header="Name" Binding="{Binding Path=Name}" CanUserResize="False" Width="*"/>
                <DataGridTextColumn Header="Time" Binding="{Binding Path=Time}" CanUserResize="False" MaxWidth="42" MinWidth="42"/>
            </DataGrid.Columns> 

Niestety dalej nie widać ikony w pierwszej kolumnie :( W kursie z http://videokurs.pl/kurs-c-sharp-tworzenie-aplikacji-wpf-xaml.php autor już ma dodany obrazek i nie wiem co jest nie tak :(

1

Ikona się nie zmienia, ponieważ nie masz we własności IconName obsłużonej metody OnPropertyChanged(). Robisz to wszystko w ogóle trochę nieprawidłowo:

  • Dlaczego np. tutaj masz wywołanie OnPropertyChanged("IconName")? Jest to nieprawidłowe podejście, ponieważ nie masz zdefiniowanej publicznej własności IconName i widok tego i tak nie zobaczy.
        public eTrackStatus TrackStatus
        {
            get { return this.trackStatus; }
            set
            {
                this.trackStatus = value;
                if (this.trackStatus == eTrackStatus.ready)
                    IconName = "Ready16" + ".png";
                if (this.trackStatus == eTrackStatus.play)
                    IconName = "Play16" + ".png";
                if (this.trackStatus == eTrackStatus.error)
                    IconName = "Error16" + ".png";
                if (this.trackStatus == eTrackStatus.next)
                    IconName = "Next16" + ".png";
                this.OnPropertyChanged("IconName"); // Tutaj powinno być `nameof(this.TrackStatus)` zamiast "IconName"
            }
        }
  • Dlaczego masz tylko prywatną własność private string IconName { get; set; } zamiast zrobić prywatne pole i publiczną własność z wywołaniem this.OnPropertyChanged(nameof(this.IconName)?
public string IconName
        {
            get { return this.iconName; }
            set
            {
                this.iconName = value;
                this.OnPropertyChanged(nameof(this.IconName));
            }
        }

Dlatego widok Ci się nie aktualizuje.

Poza tym na każdym pliku z ikonką dobrze ustawić we właściwościach takie wartości jak na tym screenie:

cc35525a1f.png

Będziesz miał wtedy pewność, że obrazek zawsze zostanie wkompilowany w exec'a.

1 użytkowników online, w tym zalogowanych: 0, gości: 1