c# - Datagrid ValueConverter based on Min or Max Value -


i'm trying change colour of datagrid cell based on if it's min or max value in observablecollection value of cell part of.

now have following datagrid , style template:

<grid itemssource="{binding mydata.myobscollection}">     <datagrid.resources>      <style targettype="{x:type datagridcell}">         <setter property="foreground">             <setter.value>                 <multibinding converter="{staticresource myvalidconverter}">                     <binding path="mdtime" /> //myobscollection doesn't work here                     <binding path="mdisvalid" />                 </multibinding>             </setter.value>          </setter>     </style>... 

the collection, simplified, consists of following:

public class myclass : inotifypropertychanged {     ...     public observablecollection<mydata> myobscollection { get; set; }...  public class mydata {     public int mdtime { get; set; }     public bool mdisvalid { get; set; }... 

this changes value of cell colour depending on "mdisvalid" bool value, fine. want extend behaviour , if mdtime in current cell value lowest in entire collection i'm binding datagrid change colour else.

the valueconverter sits in same namespace mainwindow, not within mainwindow method. have mainwindow databound viewmodel , databinding sweet as.

i cannot figure out how access collection within valueconverter. i've tried getting datacontext of parent window, nothing seems work. i've been reading valueconverters several hours, , in every single example seems follow same basic approach. none of them seem access data outside of valueconverter method that's called, , can't figure way of passing entire collection converter.

i'm sure it's simple i've overlooked...

edit: in addition sa_ddam's answer i've added code style:

<binding relativesource="{relativesource self}"/> 

and converter:

solidcolorbrush _brush = new solidcolorbrush(colors.white); var cell = (datagridcell)values[2]; string columnname = cell.column.header.tostring(); switch (columnname) {     case "mdtime":         return collection.min(x => x.mdtime).equals(collection[0].mdtime)             ? new solidcolorbrush(colors.limegreen)             : _brush;         break;     case "mdtime2":         return collection.min(x => x.mdtime2).equals(collection[0].mdtime2)             ? new solidcolorbrush(colors.limegreen)             : _brush;         break;... 

the columnname returns actual text name of column cell in. run switch on columns have.

just need @ next 1 of refreshing table min colour change applies on single row, i.e. if smallest value in collection should 1 colour else it's another. when add on collection old colour values still apply, min query on each of cells of new row. getting there ;-)

edit #2: collection[0] first in collection, obviously, , last data add, because insert position 0. checking min value against valid validation on current row i've added, not on others. grid didn't need refreshing @ all, wasted time relaycommands did nothing. showed me had issue logic, not totally wasted time ;-)

i added simple command , returns actual data of item in question:

var celldata = cell.datacontext mydata; 

then small change query , how want it:

return collection.min(x => x.mdtime).equals(celldata.mdtime) 

big sa_ddam gave me first part , fumbled way need to.

i'll leave in hope helps others out, there seems lot of "simple" tutorials on web, nothing covers complex set-up. please let me know if helps out...

you can hold of itemsource binding datagrid, use findancestor or name datagrid , use elementname in multibinding

example: (findancestor)

<datagrid itemssource="{binding mydata.myobscollection}">     <datagrid.resources>      <style targettype="{x:type datagridcell}">         <setter property="foreground">             <setter.value>                 <multibinding converter="{staticresource myvalidconverter}">                     <binding path="itemssource" relativesource="{relativesource mode=findancestor, ancestortype={x:type datagrid}}" />                                                     <binding path="mdisvalid" />                 </multibinding>             </setter.value>          </setter>     </style>... 

example: (elementname)

<datagrid x:name="datagrid" itemssource="{binding mydata.myobscollection}">     <datagrid.resources>      <style targettype="{x:type datagridcell}">         <setter property="foreground">             <setter.value>                 <multibinding converter="{staticresource myvalidconverter}">                     <binding path="itemssource" elementname="datagrid" />                                                            <binding path="mdisvalid" />                 </multibinding>             </setter.value>          </setter>     </style>... 

converter:

public object convert(object[] values, type targettype, object parameter, system.globalization.cultureinfo culture) {     if (values[0] observablecollection<mydata> && values[1] int)     {         var collection = (observablecollection<mydata>)values[0];         var time = (int)values[1];          return collection.any() && collection.max(x => x.mdtime).equals(time)             ? new solidcolorbrush(colors.red)             : new solidcolorbrush(colors.black);     }     return new solidcolorbrush(colors.black); } 

full working example

code:

namespace wpfapplication11 {     /// <summary>     /// interaction logic mainwindow.xaml     /// </summary>     public partial class mainwindow : window     {         private observablecollection<mydata> _items = new observablecollection<mydata>();          public mainwindow()         {             initializecomponent();             items.add(new mydata { title = "item1", mdtime = 1, mdtime2 =3 });             items.add(new mydata { title = "item2", mdtime = 6, mdtime2 = 50 });             items.add(new mydata { title = "item3", mdtime = 45, mdtime2 = 23 });             items.add(new mydata { title = "item4", mdtime = 3, mdtime2 = 1 });             items.add(new mydata { title = "item5", mdtime = 8, mdtime2 = 9 });          }          public observablecollection<mydata> items         {             { return _items; }             set { _items = value; }         }     }      public class mydata     {         public string title { get; set; }         public int mdtime { get; set; }         public int mdtime2 { get; set; }         public bool mdisvalid { get; set; }     }      public class maxconverter : imultivalueconverter     {         public object convert(object[] values, type targettype, object parameter, system.globalization.cultureinfo culture)         {             if (values[0] observablecollection<mydata> && values[1] datagridcell && values[2] mydata)             {                 var collection = (observablecollection<mydata>)values[0];                 var columnname = (values[1] datagridcell).column.header.tostring();                 var data = values[2] mydata;                  if (columnname.equals("mdtime") && collection.max(x => x.mdtime).equals(data.mdtime))                 {                      return new solidcolorbrush(colors.red);                 }                 else if (columnname.equals("mdtime2") && collection.min(x => x.mdtime).equals(data.mdtime))                 {                     return new solidcolorbrush(colors.blue);                 }             }             return new solidcolorbrush(colors.black);         }          public object[] convertback(object value, type[] targettypes, object parameter, system.globalization.cultureinfo culture)         {             throw new notimplementedexception();         }     } } 

xaml:

   <window x:class="wpfapplication11.mainwindow"         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"         xmlns:local="clr-namespace:wpfapplication11"         title="mainwindow" height="235" width="308" name="ui">      <grid datacontext="{binding elementname=ui}" >          <datagrid itemssource="{binding items}">             <datagrid.resources>                 <local:maxconverter x:key="myvalidconverter" />                  <style targettype="{x:type datagridcell}">                     <setter property="foreground">                         <setter.value>                             <multibinding converter="{staticresource myvalidconverter}">                                 <binding path="itemssource" relativesource="{relativesource findancestor, ancestortype={x:type datagrid}}" />                                 <binding relativesource="{relativesource self}" />                                 <binding />                             </multibinding>                         </setter.value>                     </setter>                 </style>             </datagrid.resources>         </datagrid>      </grid>  </window> 

Comments

Popular posts from this blog

Perl - how to grep a block of text from a file -

delphi - How to remove all the grips on a coolbar if I have several coolbands? -

javascript - Animating array of divs; only the final element is modified -