Java týden Java týden
Pouze tento týden sleva až 80 % na celý Java e-learning!
Brno? Vypsali jsme pro vás nové termíny školení OOP v Brně!
Avatar
Frantisek Jesatko:19.8.2018 14:18

Ahoj mam dotaz na datagrid ve wpf . muzu nejak zmenit barvu pozadi radku podle urcite hodnoty bunky ? Chybi mi Rows i Cells . nevim jestli delat v xaml nebo c#. diky za pomoc

Zkusil jsem: zkousel jsem web nic

Chci docílit: rozliseni zaznamu barevne podle urcitych hodnot

 
Odpovědět 19.8.2018 14:18
Avatar
krepsy3
Redaktor
Avatar
krepsy3:19.8.2018 15:08

To je problém s datagridem, musíš totiž změnit svůj pohled na datagrid.

Datagrid je kontrolka, která reprezentuje určitá data, která kontrolce binduješ. Což znamená, že mít z kontrolky znova přístup k datům je de facto blbost. Uvědom si, že když DataGridu binduješ určitou kolekci, tak ona ti tu kolekci zobrazí jako tabulku, kde řádky jsou obvykle položky kolekce, jejichž vlastnosti zobrazují sloupce.

A teď - máš-li kolekci dat, kterou předáš datagridu, víš, že někde v té kolekci se nacházejí i data, která se v datagridu zobrazí v buňce, podle které bys chtěl pozadí měnit.

Co z toho plyne? Že data pro barvu pozadí nemáš získat přes datagrid, ale přímo přes kolekci, kterou datagridu binduješ. Pokud chceš ode mě napsat nějaký kód, napiš, co je to za data a na základě čeho chceš pozadí měnit. Napiš mi také XAML, protože mám pocit, že to co chceš dělat se dá zakomponovat přímo do bindingu :)

Nahoru Odpovědět 19.8.2018 15:08
Programátor je stroj k převodu kávy na kód.
Avatar
Odpovídá na krepsy3
Frantisek Jesatko:19.8.2018 17:27

tady je xaml

<DataGrid x:Name="grd_uni"  HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" MinWidth="600" Margin="185,48,2,6" AlternatingRowBackground="#FFD6CECE" GridLinesVisibility="Vertical" VerticalGridLinesBrush="#FF534B4B"/>

Data do datagridu dostavam z kodu takto :

var  xxx = from z in db.Zasahs
                         from k in db.Adresars
                         from u in db.Uzivateles
                         where z.id_zakaznika == k.ico && z.id_uzivatele == u.Id
                         orderby z.datum descending
                         select new { z.id_zasahu, z.datum, k.nazev, z.pro_technika, z.popis_zavady, z.poslan_vykaz, z.fakturovano, z.fakturovany_dily, z.stav, u.prijmeni, z.upraveno, z.sdileno, z.vytvoreno, z.cislo_stroje };


          grd_uni.ItemsSource = xxx.ToList();

Kde položka fakturovano je hodnota "Ano-Ne" , fakturovany-dily je take hodnota "Ano-Ne"
Podle toho bych rád barvil řádky.
Dále potřebuju předat id z Bindingu tedy hodnotu z_idzasahu.
Díky za pomoc

 
Nahoru Odpovědět 19.8.2018 17:27
Avatar
Odpovídá na krepsy3
Frantisek Jesatko:19.8.2018 19:01

Je pravda že mam na datagrid z WF jiný pohled. Ve WPF je celý přístup uplně jiný a docela dost s tím zápasím .

 
Nahoru Odpovědět 19.8.2018 19:01
Avatar
krepsy3
Redaktor
Avatar
Odpovídá na Frantisek Jesatko
krepsy3:19.8.2018 23:47

A tu kolekci z linq dotazu tam binduješ jak?

Nahoru Odpovědět 19.8.2018 23:47
Programátor je stroj k převodu kávy na kód.
Avatar
krepsy3
Redaktor
Avatar
Odpovídá na krepsy3
krepsy3:19.8.2018 23:56

Jo aha, takže necháváš WPF, ať to dělá samo... Tak to bude stačit udělat si columntemplaty, ve kterých zrealizuješ ty změny pozadí... napiš mi přesně, co chceš, aby ty buňky dělaly

Nahoru Odpovědět 19.8.2018 23:56
Programátor je stroj k převodu kávy na kód.
Avatar
Odpovídá na krepsy3
Frantisek Jesatko:20.8.2018 6:10

Vzhledem k tomu , že přecházím z WF tak binding je věc která mi zůstává utajena. A tak nechávám vše co můžu do v cecku . Jinak teda potřebuju aby sloupec fakturováno pokud obsahuje hodnotu NE tak celý rádek barva červená .

 
Nahoru Odpovědět 20.8.2018 6:10
Avatar
Miroslav Majcher:20.8.2018 9:05

Jedna z alternativ je napisat si vlastny behavior k danemu datagridu.

/// <summary>
   ///
   /// </summary>
   public class DataGridRowLoadBackgroudBehaviour : Behavior<DataGrid>
   {
       #region OnAttached
       /// <summary>
       ///
       /// </summary>
       protected override void OnAttached()
       {
           base.OnAttached();
           AssociatedObject.LoadingRow += this.AssociatedObject_LoadingRow;
       }
       #endregion

       #region OnDetaching
       /// <summary>
       ///
       /// </summary>
       protected override void OnDetaching()
       {
           base.OnDetaching();
           AssociatedObject.LoadingRow -= this.AssociatedObject_LoadingRow;
       }
       #endregion

       #region AssociatedObject_LoadingRow
       /// <summary>
       ///
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
       void AssociatedObject_LoadingRow(object sender, DataGridRowEventArgs e)
       {
            -- v e.Row.DataContext je bindovany object
           Complaint current = e.Row.DataContext as Complaint;
           if (current != null)
           {
               if (!string.IsNullOrEmpty(current.PriorityType))
               {
                   -- tu sa vyhodnocuje, kedy ma mat row inu farbu.
                   if (current.PriorityType.ToUpper() == "A")
                       e.Row.Background = new SolidColorBrush(Colors.Red);
                   else
                       e.Row.Background = null;
               }
               else
                   e.Row.Background = null;
           }
           else
               e.Row.Background = null;
       }
       #endregion
   }

V XAML pre prislusny DataGrid:

<i:Interaction.Behaviors>
         <cUtils:DataGridRowLoadBackgroudBehaviour/>
 </i:Interaction.Behaviors>

kde i je z

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

Kod je kopirovany zo Silverlightu, z jedneho mojho projektu. Bude potreba ho prejst, upravit na WPF, ale princip cez behavior je rovnaky.

M.

 
Nahoru Odpovědět 20.8.2018 9:05
Avatar
Odpovídá na Frantisek Jesatko
Matyáš Černohous:20.8.2018 17:07

Něco podobného jsem řešil. Dělám to přesně tak jak psal krepsy3. Do DataGridu nabinduju kolekci a změnu dat (např. změna barvy pozadí jedné buňky nebo celého řádku) provádím přes controller. Model implementuje rozhraní INotifyProper­tyChanged, takže kdykoliv změním nějaký item, který mám v kolekci, tak se změna hned projeví v DataGridu.
Binding je sám o sobě dost užitečná věc, protože vlastně můžeš díky tomu měnit skoro jakoukoliv vlastnost.

Tady je moje řešení. Je zde binding dat do jednotlivých DataGridTextCo­lumnů. Nevím jak to je přesně, ale vypadá to, že dědí z textBoxu, takže přes setter můžeš upravovat jakoukoli vlastnost jako kdyby si pracoval s TextBoxem - tudíž i barvu pozadí/textu/rá­mečku... (

<Setter Property="TextBlock.Background" Value="{Binding Color}" />

)

Níže je kód modelu a poté controlleru.

<DataGrid  ItemsSource="{Binding}" HorizontalScrollBarVisibility="Hidden" RowHeaderWidth="0" x:Name="data" Background="White" HorizontalAlignment="Stretch"
                  Margin="1,5" VerticalAlignment="Stretch" BorderBrush="Black" BorderThickness="2,0,2,2" AutoGenerateColumns="False" CanUserResizeRows="False" GridLinesVisibility="All"
                  ScrollViewer.ScrollChanged="data_ScrollChanged" ScrollViewer.CanContentScroll="True" ColumnHeaderDragCompleted="data_ColumnHeaderDragCompleted"
                  LayoutUpdated="data_LayoutUpdated" IsReadOnly="True" CanUserReorderColumns="False" CanUserSortColumns="False" UseLayoutRounding="False" IsManipulationEnabled="True"
                  PreviewMouseWheel="data_PreviewMouseWheel" IsHitTestVisible="False" FontSize="11" FontFamily="Tahoma" >
           <DataGrid.Resources>
               <Style TargetType="{x:Type DataGridCell}">
                   <Style.Triggers>
                       <Trigger Property="DataGridCell.IsSelected" Value="True">
                           <Setter Property="Background" Value="White" />
                           <Setter Property="BorderBrush" Value="Transparent" />
                           <Setter Property="Foreground" Value="Black"/>
                       </Trigger>
                   </Style.Triggers>
               </Style>
           </DataGrid.Resources>
           <DataGrid.Columns>
               <DataGridTextColumn Binding="{Binding Podsestava}" util:DataGridUtil.Name="ses" ClipboardContentBinding="{x:Null}" Header="Podsestava" FontFamily="Tahoma" FontSize="11" >
                   <DataGridTextColumn.ElementStyle>
                       <Style>
                           <Setter Property="TextBlock.TextWrapping" Value="Wrap" />
                       </Style>
                   </DataGridTextColumn.ElementStyle>
               </DataGridTextColumn>
               <DataGridTextColumn Binding="{Binding Pozice}" IsReadOnly="True" util:DataGridUtil.Name="poz" ClipboardContentBinding="{x:Null}" Header="Pozice" FontFamily="Tahoma" FontSize="11">
                   <DataGridTextColumn.ElementStyle>
                       <Style>
                           <Setter Property="TextBlock.TextWrapping" Value="Wrap" />
                           <Setter Property="TextBlock.Cursor" Value="Hand"></Setter>
                           <EventSetter Event="TextBlock.MouseDown" Handler="Click"  />
                           <Setter Property="TextBlock.Background" Value="{Binding Color}" />
                       </Style>
                   </DataGridTextColumn.ElementStyle>
               </DataGridTextColumn>
               <DataGridTextColumn Binding="{Binding Nazev}" util:DataGridUtil.Name="naz" ClipboardContentBinding="{x:Null}" Header="Název" FontFamily="Tahoma" FontSize="11">
                   <DataGridTextColumn.ElementStyle>
                       <Style>
                           <Setter Property="TextBlock.TextWrapping" Value="Wrap" />
                       </Style>
                   </DataGridTextColumn.ElementStyle>
               </DataGridTextColumn>
               <DataGridTextColumn Binding="{Binding Poznamka}" util:DataGridUtil.Name="pozn" ClipboardContentBinding="{x:Null}" Header="Poznámka" FontFamily="Tahoma" FontSize="11">
                   <DataGridTextColumn.ElementStyle>
                       <Style>
                           <Setter Property="TextBlock.TextWrapping" Value="Wrap" />
                       </Style>
                   </DataGridTextColumn.ElementStyle>
               </DataGridTextColumn>
           </DataGrid.Columns>
           <DataGrid.ColumnHeaderStyle>
               <Style TargetType="{x:Type DataGridColumnHeader}">
                   <Setter Property="Background" Value="White"/>
                   <Setter Property="Foreground" Value="Black" />
                   <Setter Property="Margin" Value="0,0,0,0" />
                   <Setter Property="HorizontalContentAlignment" Value="Left" />
                   <Setter Property="BorderThickness" Value="0,2,1,2" />
                   <Setter Property="BorderBrush" Value="Black" />
                   <Setter Property="FontWeight" Value="Bold" />


               </Style>
           </DataGrid.ColumnHeaderStyle>


       </DataGrid>

Model:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace DokumentacePriprava
{
    public class Rozpiska : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public string Podsestava { get; set; }
        public string Pozice { get; set; }
        public string Nazev { get; set; }
        public string Dodavatel { get; set; }
        public string Poznamka { get; set; }

        private string color;

        public string Color
        {
            get { return color; }
            set
            {
                color = value;
                NotifyPropertyChanged();

            }
        }

        public Rozpiska(string podsestava, string pozice, string nazev, string dodavatel, string poznamka)
        {
            Podsestava = podsestava;
            Pozice = pozice;
            Nazev = nazev;
            Dodavatel = dodavatel;
            Poznamka = poznamka;
            Color = "Transparent";

        }

//tohle je nepodstatný
        public string ConvertType(bool en)
        {
            if (en)
            {
                if (SettingsHelper.TypeValues.ContainsKey(TypDiluOrig))
                    return SettingsHelper.TypeValues[TypDiluOrig].Item2;
                else
                    return TypDilu;
            }
            else
            {
                if (SettingsHelper.TypeValues.ContainsKey(TypDiluOrig))
                    return SettingsHelper.TypeValues[TypDiluOrig].Item1;
                else
                    return TypDilu;
            }
        }
    }
}

a controller:

public class RozpiskaController
    {
        private ObservableCollection<Rozpiska> rozpiska = new ObservableCollection<Rozpiska>();

        public RozpiskaController()
        {
        }

                //pridani itemu do kolekce
        public void Add(Rozpiska r)
        {
                rozpiska.Add(r);
        }

                public ObservableCollection<Rozpiska> GetCollection()
        {
            return rozpiska;
        }

//Změna barvy itemu v kolekci - pokud se item z kolekce rovná itemu u kterého chceš zněnit barvu, tak se provede nastavení barvy z paramentru a ihned se ti projeví změna v DataGridu
          public void ChangeColor(Rozpiska r, string hexColor)
        {
            foreach (var rozp in rozpiska)
            {
                if (rozp.Equals(r))
                {
                    rozp.Color = hexColor;
                    break;
                }
            }
        }
}

Vytvoříš si instanci controlleru a přidáš tam itemy. Dále nastavíš u DataGridu ItemSoource na tvoji kolekci a data se zobrazí v DataGridu. Dále pak jen používáš metody z Controlleru. Logiku si doplň podle toho co potřebuješ.

Příklad použití - např po načtení hlavního okna:

private void Window_Loaded(object sender, RoutedEventArgs e)
       {
                       //vytvoreni instance controlleru
                       RozpiskaController rController = new RozpiskaController();
                       //pridani itemu do controlleru
                       rController.Add(new Rozpiska("podst","152","test1","dodavatel","pozn");
                       rController.Add(new Rozpiska("podst1","2","test2545","dodavatel12","pozn heslo");
                       rController.Add(new Rozpiska("ledňáček","1982","popart","kofola","nejlepší vzpomínky");


               //nastavení ItemSource na kolekci
               data.ItemSource = rController.GetCollection();
               //Ted by si tam měl mít zobazeny data

               //změna barvy políčka pozice, pokud se item v kolekci bude rovnat itemu v parametru
               Rozpiska r  = new Rozpiska("podst1","2","test2545","dodavatel12","pozn heslo");
               rController.ChangeColor(r,"#8ff442"); //Druhý řádek bude mít políčko v řádku pozice obarvený na zeleno
               }

Snad ti to pomůže :)

Editováno 20.8.2018 17:07
Akceptované řešení
+20 Zkušeností
+1 bodů
Řešení problému
 
Nahoru Odpovědět 20.8.2018 17:07
Avatar
Odpovídá na Matyáš Černohous
Frantisek Jesatko:21.8.2018 19:42

diky za navod je az s podivem jak tak jednoduchou vec jde resit slozite. Tim nechci narazet na tebe to vubec :) ale na cely wpf . chapu ze oddelit vzhled od logiky je prehledny ale vrstva ktera obe veci propoji je mi fakt prozatim utajena .

 
Nahoru Odpovědět 21.8.2018 19:42
Avatar
Bruce
Člen
Avatar
Odpovídá na Frantisek Jesatko
Bruce:28.8.2018 14:37

Taky by to slo udelat pres DataTriggery asi takto

<Style TargetType="Da­taGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding NetworkChecked}" Value="True">
<Setter Property="Bac­kground" Value="Green" />
</DataTrigger>
<DataTrigger Binding="{Binding NetworkChecked}" Value="False">
<Setter Property="Bac­kground" Value="Orange" />
</DataTrigger>
<DataTrigger Binding="{Binding NetworkDataIm­ported}" Value="False">
<Setter Property="Bac­kground" Value="White" />
</DataTrigger>
</Style.Triggers>
</Style>

 
Nahoru Odpovědět  +1 28.8.2018 14:37
Avatar
Odpovídá na Bruce
Frantisek Jesatko:29.8.2018 20:10

Ahoj tak toto řešení je uplně nejlepší jednoduchý jako problém sám díky

 
Nahoru Odpovědět 29.8.2018 20:10
Avatar
Karel Labonek:1.12.2018 17:02

Ahoj, rád bych požádal někoho zkušenějšího než jsem já o radu. Zasek jsem se na naprosté banalitě, kterou je načtení konkrétní hodnoty buňky v označeném řádku DataGridu. DataGrid je navázaný na DataTable. Obsahuje i sloupec "Id" jehož hodnotu chci použít pro zobrazení v dalším DataGridu. Děkuji za pomoc.

už jsem zkusil něco jako toto:

private void dataGrid_kategorie_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

              DataView DVvybrany = new DataView(sprKonkretni.dtKonkretni);

            DataRowView drv = dataGrid_kategorie.SelectedItem as DataRowView ;
            string id = drv.Row[0].ToString();
            DVvybrany.RowFilter = "Id_Kategorie_tech = id";
            dataGrid_konkretni.ItemsSource = DVvybrany;
        }

Ale někde je chyba v proměnné "Id" mám sice správnou hodnotu ale do druhého DataGridu mi to načte jen první dva záznami v pořadí(nezávisle na řádku který jsem vybral v druhém DataGridu) naopak pokud nahradím proměnou "Id" za čílici např."2" vše funguje správně :( .
Ještě jednou děkuji.

 
Nahoru Odpovědět 1.12.2018 17:02
Avatar
Karel Labonek:1.12.2018 17:53

Zase jsem se o kousek posunul.
Tak to vypadá že problém mám až při použití "RowFilter".
nefunguje totiž ani toto:

int a = 2;
            DVvybrany.RowFilter = "Id_Kategorie_tech = a";

je jasné že to čeká za "=" číslo a ne jen ukazatel(proměnou).
ale jak to obejít sloupec"Id_Ka­tegorie_tech" mám v DB jako int.
Děkuji

Editováno 1.12.2018 17:54
 
Nahoru Odpovědět 1.12.2018 17:53
Avatar
Odpovídá na Karel Labonek
Frantisek Jesatko:1.12.2018 23:11

ahoj myslim ze by stacilo toto:

DVvybrany.RowFilter = "Id_Kategorie_tech = ‘a’”;
 
Nahoru Odpovědět 1.12.2018 23:11
Avatar
Odpovídá na Frantisek Jesatko
Karel Labonek:2.12.2018 4:59

Ahoj, děkuji za rychlou reakci na můj dotaz, bohužel to to jsem zkoušel.

s a => Additional information: Sloupec [a] nelze najít.
s ‘a’ => Additional information: Sloupec [‘a’] nelze najít.
s [‘a’] => Additional information: Sloupec [‘a’] nelze najít.
s [a] => Additional information: Sloupec [a] nelze najít.

Já jsem začátečník tak příliš nevidím pod pokličku některým funkcím, zde se zdá že funkce "RowFilter" v tom mém případě očekává místo "a" číslo. Našel jsem na Netu tuto stránku kde je to shrnuté. DataView RowFilter Syntax [C#]

 
Nahoru Odpovědět 2.12.2018 4:59
Avatar
Karel Labonek:5.12.2018 7:33

Zdravím, tak jsem našel řešení. Jak už to v programování bývá řešení bylo zcela banální. Pokud je snad někdo v začátcích s programováním jako já tak by mu to možná mohlo pomoci. Tak problém jsem měl se zadáváním hodnot do "RowFiltr" který se používá pro filtrování instance třídy "DataView" který mi slouží jako "ItemsSource" pro "DataGrid". Nevěděl jsem jak předat hodnoty které budou známi až při běhu App. Např. jak předat hodnotu typu "int" pomocí proměnné.

int a = 2;
            DVvybrany.RowFilter = "Id_Kategorie_tech = a";  //Takto to nefunguje !!!

No řešení je vzpomenout si na práci s řetězci string:

int a = 2;
string nazevSloupce = Id_Kategorie_tech;
        DVvybrany.RowFilter = string.Format("{0} = '" + a + "'", nazevSloupce);
Editováno 5.12.2018 7:36
 
Nahoru Odpovědět 5.12.2018 7:33
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 17 zpráv z 17.