Thursday, 21 June 2012

WPF DataGrid change cell value based on underlying data object

XAML

<Window x:Class="DataGridCellBackground.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:DataGridCellBackground="clr-namespace:DataGridCellBackground"
    Title="MainWindow" Height="350" Width="525"
    DataContext="{Binding RelativeSource={RelativeSource Self}}">
  <Window.Resources>    
    <DataGridCellBackground:DataGridCellValueConverter x:Key="dataGridCellValueConverter"/>
  </Window.Resources>
  <Grid>    
    <DataGrid ItemsSource="{Binding Data}" Width="400" Height="200" CanUserAddRows="False">
      <DataGrid.CellStyle>
        <Style TargetType="{x:Type DataGridCell}">
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="DataGridCell">                
                <TextBlock>
                  <ContentPresenter>
                    <ContentPresenter.Content>
                      <MultiBinding Converter="{StaticResource dataGridCellValueConverter}" >
                        <MultiBinding.Bindings>
                          <Binding RelativeSource="{RelativeSource AncestorType={x:Type DataGridCell}}"></Binding>
                          <Binding Path="Row"></Binding>
                        </MultiBinding.Bindings>
                      </MultiBinding>
                    </ContentPresenter.Content>
                  </ContentPresenter>
                </TextBlock>                
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </Style>
      </DataGrid.CellStyle>
    </DataGrid>    
  </Grid>
</Window>

Code Behind

namespace DataGridCellBackground
{  
  public partial class MainWindow : Window
  {
    public MainWindow()
    {           
      InitializeComponent();            
    }
 
    public DataTable Data { 
      get{
        var data = new DataTable();
  
        data.Columns.Add("Text", typeof(string));
        data.Columns.Add("Value", typeof(ComplexValue));
  
        var row = data.NewRow();
        row["Text"] = "First";
        row["Value"] = new ComplexValue() { Value = 1, Checked = true };
        data.Rows.Add(row);
 
        row = data.NewRow();
        row["Text"] = "Second";
        row["Value"] = new ComplexValue() { Value = 2, Checked = false };
        data.Rows.Add(row);
 
        row = data.NewRow();
        row["Text"] = "Third";
        row["Value"] = new ComplexValue() { Value = 3, Checked = true };
        data.Rows.Add(row);
     
        return data;
      }
    } 
 
  public class ComplexValue
  {
    public int Value { get; set; }
    public bool Checked { get; set; }
  }
}
 
  public class DataGridCellValueConverter : IMultiValueConverter
  {
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
      if (values.Length>0 && values[1] is DataRow)
      {
        var cell = (DataGridCell)values[0];
        var row = (DataRow)values[1];
        var columnName = cell.Column.SortMemberPath;
        var value = row[columnName];
        if (value is MainWindow.ComplexValue)
        {
          return (value as MainWindow.ComplexValue).Value;
        }else
        {
          return value;
        }               
      }
      return null;
    }
    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
      throw new System.NotImplementedException();
    }
  }
}

Wednesday, 20 June 2012

WPF Toggle button group

<StackPanel>
  <RadioButton Content="Left" Style="{StaticResource {x:Type ToggleButton}}" />
  <RadioButton Content="Right" tyle="{StaticResource {x:Type ToggleButton}}" />                
</StackPanel>

Tuesday, 19 June 2012

WPF DataGrid change cell style based on underlying data object

XAML

<Window x:Class="DataGridCellBackground.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:DataGridCellBackground="clr-namespace:DataGridCellBackground"
    Title="MainWindow" Height="350" Width="525"
    DataContext="{Binding RelativeSource={RelativeSource Self}}">
  <Window.Resources>
    <DataGridCellBackground:DataGridCellBackgroundConverter x:Key="dataGridCellBackgroundConverter"/>
  </Window.Resources>
  <Grid>    
    <DataGrid ItemsSource="{Binding Data}" Width="400" Height="200">
      <DataGrid.CellStyle>
        <Style TargetType="{x:Type DataGridCell}">
          <Setter Property="Background">
            <Setter.Value>
              <MultiBinding Converter="{StaticResource dataGridCellBackgroundConverter}" >
                <MultiBinding.Bindings>
                  <Binding RelativeSource="{RelativeSource Self}"></Binding>
                  <Binding Path="Row"></Binding>
                </MultiBinding.Bindings>
              </MultiBinding>
            </Setter.Value>
          </Setter>
        </Style>
      </DataGrid.CellStyle>
    </DataGrid>    
  </Grid>
</Window>

Code Behind

namespace DataGridCellBackground
{
  public partial class MainWindow : Window
  {
    public MainWindow()
    {           
      InitializeComponent();      
    }
    public DataTable Data { 
    get{
      var data = new DataTable();
      data.Columns.Add("Text", typeof(string));
      data.Columns.Add("Value", typeof(ComplexValue));
      var row = data.NewRow();
      row["Text"] = "First";
      row["Value"] = new ComplexValue() { Value = 1, Checked = true };
      data.Rows.Add(row);
      row = data.NewRow();
      row["Text"] = "Second";
      row["Value"] = new ComplexValue() { Value = 2, Checked = false };
      data.Rows.Add(row);
      row = data.NewRow();
      row["Text"] = "Third";
      row["Value"] = new ComplexValue() { Value = 3, Checked = true };
      data.Rows.Add(row);
      return data;
    }
    } 
    public class ComplexValue
    {
    public int Value { get; set; }
    public bool Checked { get; set; }
    //required for default template
    public override string ToString()
    {
      return Value.ToString();
    }
    }
  }
  public class DataGridCellBackgroundConverter : IMultiValueConverter
  {
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
    if (values[1] is DataRow)
    {                
      var cell = (DataGridCell)values[0];
      var row = (DataRow)values[1];
      var columnName = cell.Column.SortMemberPath;
      var value = row[columnName];
      if (value is MainWindow.ComplexValue)
      {
      if((value as MainWindow.ComplexValue).Checked)
      {
        return new SolidColorBrush(Colors.LightGreen);
      }
      }
    }
    return SystemColors.AppWorkspaceColor;
    }
    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
    throw new System.NotImplementedException();
    }
  }
}

Friday, 15 June 2012

HTML Table css style reference

css-table
<html>
  <head>
    <link rel="stylesheet" href="table.css"/>
  </head>
  <body>	     
    <table class="table1">
      <thead>
        <tr>
          <th width="120px"></th>
          <th width="100px">Column1</th>
          <th width="100px">Column2</th>
        </tr>
      </thead>			
      <tbody>
        <tr>
          <th scope="row">Row1</th>
          <td>1.1</td>        
          <td>1.2</td>
        </tr>
        <tr>
          <th scope="row">Row2</th>
          <td>2.1</td>        
          <td>2.2</td>
        </tr>        
      </tbody>
      <tfoot>
        <tr>
          <th scope="row">Totals</th>
          <td><div>1st Footer</div></td>
          <td><div>2nd Footer</div></td>
        </tr>
      </tfoot>
    </table>
    <p/>
		
    <table class="table2">
      <tbody>
        <tr>
          <td>Sample</td>
        </tr>
        <tr>
          <td>Sample</td>
        </tr>			
        <tr>
          <td>Sample</td>
        </tr>				
        </tbody>
    </table>
		
    <p/>
		
    <span>A</span>
    <span class="test">B</span>
    <span id="test">C</span>
							
  </body>
</html>
body,td,th
{
    font-size: 10px;
	font-style: normal;
    font-family: sans-serif    
}
table
{	        
    border-collapse:separate;	
	border-spacing:0px;
}
thead th{
    padding:2px;
    color:#fff;    
    /*border:1px solid #aeaeae; */
    background-color:#C0C0C0;  
	border-bottom:1px solid #fff;
	border-right:1px solid #fff;	
}
thead th:empty{
    background:transparent;
    border:none;
}
tbody td{
    padding:2px;
    text-align:right;
    background-color:#E0E0E0;
    /*border: 2px solid #E7EFE0;*/
    color:#666;    
    border-bottom:1px solid #fff;
	border-right:1px solid #fff;
}
tbody th{
    padding:2px;
    text-align:left;
    background-color:#B0B0B0;
    /*border: 2px solid #E7EFE0;*/
    color:#666;    
	border-bottom:1px solid #fff;
	border-right:1px solid #fff;
}
tfoot th{
    color:#666;
	background-color:#888888;
}
tfoot td{
	background-color:#C0C0C0;
    color: #666;	
/*	vertical-align:center;
	text-align:center;*/
}
/*rotate div by 90 degrees*/
div{
  -webkit-writing-mode:vertical-rl;
  text-align:center;
  margin: auto;
}
/*apply styles only to table with class="table2"*/
table.table2 tbody tr:nth-child(even) {
	background:#B0B0B0;
}
table.table2 tbody tr:nth-child(odd) {
	background:#E0E0E0;
}
table.table2 tbody td {
	background:transparent;
}
/*apply style to all span tags*/
span {
    color:blue;	
}
/*apply style to span tags with class="test"*/
span.test {
    color:red;	
}
/*apply style to span tags with id="test"*/
span#test {
    color:green;	
}

Thursday, 14 June 2012

C# Regex replace

[Test]
public void TestRegexReplace()
{
  //replace A or B with X after \Date\
  var pattern = @"\b(?<=\\Date\\)(A|B)\b";
  
  Assert.AreEqual(
	@"c:\temp\Date\X\SubFolder\",
	Regex.Replace(@"c:\temp\Date\A\SubFolder\", pattern, m => "X"));
  
  Assert.AreEqual(
	@"c:\temp\Date\X\SubFolder\",
	Regex.Replace(@"c:\temp\Date\B\SubFolder\", pattern, m => "X"));
  
  Assert.AreEqual(
	@"c:\temp\Date\C\SubFolder\", Regex.Replace(
	@"c:\temp\Date\C\SubFolder\", pattern, m => "X"));
  
  //or the simple way :)
  
  pattern = @"\\Date\\[AB]\\";
  
  Assert.AreEqual(
	@"c:\temp\Date\X\SubFolder\",
	Regex.Replace(@"c:\temp\Date\A\SubFolder\", pattern, m => @"\Date\X\"));
  
  Assert.AreEqual(
	@"c:\temp\Date\X\SubFolder\",
	Regex.Replace(@"c:\temp\Date\B\SubFolder\", pattern, m => @"\Date\X\"));
  
  Assert.AreEqual(
	@"c:\temp\Date\C\SubFolder\", Regex.Replace(
	@"c:\temp\Date\C\SubFolder\", pattern, m => @"\Date\X\"));
}

Update Log4Net file name programmatically

//update log file name
public static bool ChangeLogFileName(string appenderName, string newFilename)
{            
  var rootRepository = log4net.LogManager.GetRepository();
  foreach (var appender in rootRepository.GetAppenders())
  {
    if (appender.Name.Equals(appenderName) && appender is log4net.Appender.FileAppender)
    {
      var fileAppender = appender as log4net.Appender.FileAppender;
      fileAppender.File = newFilename;
      fileAppender.ActivateOptions();
      return true;  // Appender found and name changed to NewFilename
    }
  }
  return false; // appender not found
}
//usage
ChangeLogFileName("RollingFileAppender", "MyLogName.log");

Sample log4net configuration from App.config, for more info see this post

//App.config configuration
<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
  </configSections>
  
  <log4net>
    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="Log\\App.log"/>
      <appendToFile value="true"/>
      <rollingStyle value="Date"/>
      <datePattern value=".yyyyMMdd"/>
      <maxSizeRollBackups value="7"/>
      <staticLogFileName value="true"/>
      <threshold value="INFO"/>
      <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%d [%t] %-5p %c.%M():%L - %m%n"/>
      </layout>
    </appender>
    <logger name="MyCompany">
      <appender-ref ref="RollingFileAppender"/>
    </logger>
  </log4net>
  
</configuration>