none
DataGrid Column Header text change from ViewModel

    Question

  • Hi,

    I need to change the column header text of the datagrid. I have defined a viewmodel and exposed a property, but I am not sure how I can bind the column header to this property.

    I am trying to follow MVVM patern and using prism. I am very new to this and I am almost getting lost.

    How can I resolve this problem

    I am using Silverlight4 and VS2010


    Thanks

    ab


    Monday, September 13, 2010 4:15 PM

Answers

  • Thanks

    I found another article  ...

    its not neat .. but will work for me...

    Monday, September 20, 2010 8:15 PM
  • I dont remember the link to the article.
    In case I get I can post it.
    Right now I am pasting the code I have
    <UserControl
    x:Class="ccc.RI.SMViewDefault.View.DefaultListView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" 
    xmlns:conv="clr-namespace:ccc.RI.Common.Converters;assembly=ccc.RI.Common"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
    <UserControl.Resources>
    <conv:BooleanFontConverter x:Key="boofont"></conv:BooleanFontConverter>
            <conv:BindingConverter x:Key="BindCon"/>
            <Style x:Key="ColBinding" TargetType="sdk:DataGridColumnHeader" >
                <Setter Property="ContentTemplate" >
                    <Setter.Value>
                        <DataTemplate>
                            <ContentPresenter Content="{Binding Converter={StaticResource BindCon}}"  />
                        </DataTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            
            <DataTemplate x:Key="ParticipantCol">
                <Grid>
                    <TextBlock Text="{Binding ParticipantName}" FontWeight="{Binding IsRead,Converter={StaticResource boofont}}" Margin="0,4"
    ></TextBlock>
                </Grid>
            </DataTemplate>
            
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" HorizontalAlignment="Stretch" Margin="1,0,1,11">
            <TextBox Text="{Binding GetParticipantHeader}" x:Name="participantHeader" />
            
    <Border BorderBrush="#FFA6B6D6" BorderThickness="2" CornerRadius="2"
    x:Name="defaultview">
    <sdk:DataGrid ItemsSource="{Binding Path=GetMessages}" 
     AutoGenerateColumns="False" 
                              ColumnHeaderStyle="{StaticResource ColBinding}"
     >
    <sdk:DataGrid.Columns >
                        
                        
                        <sdk:DataGridTemplateColumn 
                            CellTemplate="{StaticResource ParticipantCol}" 
                            Header="{Binding Text, ElementName=participantHeader}"
                            Width="1*"  
                            SortMemberPath="ParticipantName"/>
                        
                        
    </sdk:DataGrid.Columns>
    </sdk:DataGrid>
    </Border>
    </Grid>
    </UserControl>
    Also u need a converter.
    namespace ccc.RI.Common.Converters
    {
        public class BindingConverter  : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                if (value.GetType().Name == "Binding")
                {
                    ContentControl cc = new ContentControl();
                    Binding newValue = value as Binding;
                    newValue.Mode = BindingMode.TwoWay;
                    cc.SetBinding(ContentControl.ContentProperty, newValue as Binding);
                    return cc;
                }
                else
                {
                    return value;
                }
            }
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                return null;
            }
        }
    }
    Hope this helps

    I dont remember the link to the article.


    In case I get I can post it.


    Right now I am pasting the code I have


    <UserControl

    x:Class="ccc.RI.SMViewDefault.View.DefaultListView"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" 

    xmlns:conv="clr-namespace:ccc.RI.Common.Converters;assembly=ccc.RI.Common"

    mc:Ignorable="d"

    d:DesignHeight="300" d:DesignWidth="400">

    <UserControl.Resources>

    <conv:BooleanFontConverter x:Key="boofont"></conv:BooleanFontConverter>

            <conv:BindingConverter x:Key="BindCon"/>

            <Style x:Key="ColBinding" TargetType="sdk:DataGridColumnHeader" >

                <Setter Property="ContentTemplate" >

                    <Setter.Value>

                        <DataTemplate>

                            <ContentPresenter Content="{Binding Converter={StaticResource BindCon}}"  />

                        </DataTemplate>

                    </Setter.Value>

                </Setter>

            </Style>

            

            <DataTemplate x:Key="ParticipantCol">

                <Grid>

                    <TextBlock Text="{Binding ParticipantName}" FontWeight="{Binding IsRead,Converter={StaticResource boofont}}" Margin="0,4"

    ></TextBlock>

                </Grid>

            </DataTemplate>

            

    </UserControl.Resources>


    <Grid x:Name="LayoutRoot" HorizontalAlignment="Stretch" Margin="1,0,1,11">

            <TextBox Text="{Binding GetParticipantHeader}" x:Name="participantHeader" />

            

    <Border BorderBrush="#FFA6B6D6" BorderThickness="2" CornerRadius="2"

    x:Name="defaultview">

    <sdk:DataGrid ItemsSource="{Binding Path=GetMessages}" 

     AutoGenerateColumns="False" 

                              ColumnHeaderStyle="{StaticResource ColBinding}"

     >

    <sdk:DataGrid.Columns >

                        

                        

                        <sdk:DataGridTemplateColumn 

                            CellTemplate="{StaticResource ParticipantCol}" 

                            Header="{Binding Text, ElementName=participantHeader}"

                            Width="1*"  

                            SortMemberPath="ParticipantName"/>

                        

                        

    </sdk:DataGrid.Columns>

    </sdk:DataGrid>

    </Border>

    </Grid>

    </UserControl>



    Also u need a converter.


    namespace ccc.RI.Common.Converters

    {

        public class BindingConverter  : IValueConverter

        {


            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

            {

                if (value.GetType().Name == "Binding")

                {

                    ContentControl cc = new ContentControl();

                    Binding newValue = value as Binding;

                    newValue.Mode = BindingMode.TwoWay;

                    cc.SetBinding(ContentControl.ContentProperty, newValue as Binding);

                    return cc;

                }

                else

                {

                    return value;

                }

            }


            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

            {

                return null;

            }

        }

    }



    Hope this helps

    Tuesday, September 21, 2010 8:44 AM

All replies

  • I am not sure if you can, the last I looked at binding Headers was in SL 3 but back then it was not a FrameworkElement so you could not bind to it. Not sure if it changed since then.

    Can you post your xaml for the grid and your viewmodel bind property? 

    Monday, September 13, 2010 4:57 PM
  • What I am trying to do is very similar to an Email Client. When you click on th Inbox folder I need to show the Header for the recipient as "From" when in Send folder change the Header for the recipient as "To" If I can change this, I can use the same view for all the folders clicked, thats the plan. xaml



           <UserControl.Resources>
    		<DataTemplate x:Key="CheckboxGrid">
    			<Grid>
    				<CheckBox IsThreeState="False" 	IsChecked="False"/>
    			</Grid>			
    		</DataTemplate>
    	</UserControl.Resources>
        
        <Grid x:Name="LayoutRoot" Background="Aqua" HorizontalAlignment="Stretch" Margin="2,0" >
    
            <sdk:DataGrid ItemsSource="{Binding GetMessages}" AutoGenerateColumns="False" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch">
        		<sdk:DataGrid.Columns >
        			<sdk:DataGridTemplateColumn CellTemplate="{StaticResource CheckboxGrid}" Width="SizeToCells"/>
                    <sdk:DataGridTextColumn x:Name="ColParicipant" Binding="{Binding ParticipantName}" Header="From" IsReadOnly="True" Width="1*"/>
    				<sdk:DataGridTextColumn x:Name="ColFacility" Binding="{Binding FacilityName}" Header="Facility"  IsReadOnly="True" Width="1*"/>
    				<sdk:DataGridTextColumn x:Name="ColPatient" Binding="{Binding PatientName}" Header="Patient Name"  IsReadOnly="True" Width="1*"/>
    				<sdk:DataGridTextColumn x:Name="ColSubject" Binding="{Binding Subject}" Header="Subject"  IsReadOnly="True" Width="1*"/>
    				<sdk:DataGridTextColumn x:Name="ColTime" Binding="{Binding Timestamp}" Header="Timestamp" IsReadOnly="True" Width="*"/>
        		</sdk:DataGrid.Columns>
    		</sdk:DataGrid>
        </Grid>

    public partial class MessageListView : UserControl
        {
            public MessageListView(MessageListVM viewModel)
            {
                InitializeComponent();
    
                this.Loaded += (s, e) =>
                {
                    this.DataContext = viewModel;
                };
            }
    
        }





    (ViewModel)
    public class MessageListVM
        {
            public MessageListVM(IMessageService messageService)
            {
                this.messageService = messageService;
            }
    
            public IEnumerable<Message> GetMessages
            {
                get
                {
                    return messageService.GetFolderMessages();
                }
            }
    
            public object GetHeader
            {
                get
                {
                    return "From";
                }
            }
            private readonly IMessageService messageService;
        }




    Monday, September 13, 2010 5:26 PM
  • Have a look at this post, as you will see it is still not small task to achieve this.

     

    http://forums.silverlight.net/forums/p/176929/398718.aspx 

    Monday, September 13, 2010 5:40 PM
  • thanks....

    I could get this working by creating the ViewModel as a local resource, and by providing a empty constructor for the viewmodel.

    But I also set the datacontext to the same viewmdoel during load event of the view.

    Is it right to do this? Will it create 2 instance of the same viewmodel ? I can post the code for this if required.

    Tuesday, September 14, 2010 12:42 PM
  • A StaticResource declared ViewModel will create a new instance unless you use a ViewModel locator pattern. If you go this route maybe use your StaticResource ViewModel across your view and rather not set the DataContext on the load event.

    http://johnpapa.net/silverlight/simple-viewmodel-locator-for-mvvm-the-patients-have-left-the-asylum/ 

    Tuesday, September 14, 2010 2:00 PM
  • Thanks

    I found another article  ...

    its not neat .. but will work for me...

    Monday, September 20, 2010 8:15 PM
  • Would you mind posting the link of that article here to share with other communites.

    Monday, September 20, 2010 10:01 PM
  • I dont remember the link to the article.
    In case I get I can post it.
    Right now I am pasting the code I have
    <UserControl
    x:Class="ccc.RI.SMViewDefault.View.DefaultListView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" 
    xmlns:conv="clr-namespace:ccc.RI.Common.Converters;assembly=ccc.RI.Common"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
    <UserControl.Resources>
    <conv:BooleanFontConverter x:Key="boofont"></conv:BooleanFontConverter>
            <conv:BindingConverter x:Key="BindCon"/>
            <Style x:Key="ColBinding" TargetType="sdk:DataGridColumnHeader" >
                <Setter Property="ContentTemplate" >
                    <Setter.Value>
                        <DataTemplate>
                            <ContentPresenter Content="{Binding Converter={StaticResource BindCon}}"  />
                        </DataTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            
            <DataTemplate x:Key="ParticipantCol">
                <Grid>
                    <TextBlock Text="{Binding ParticipantName}" FontWeight="{Binding IsRead,Converter={StaticResource boofont}}" Margin="0,4"
    ></TextBlock>
                </Grid>
            </DataTemplate>
            
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" HorizontalAlignment="Stretch" Margin="1,0,1,11">
            <TextBox Text="{Binding GetParticipantHeader}" x:Name="participantHeader" />
            
    <Border BorderBrush="#FFA6B6D6" BorderThickness="2" CornerRadius="2"
    x:Name="defaultview">
    <sdk:DataGrid ItemsSource="{Binding Path=GetMessages}" 
     AutoGenerateColumns="False" 
                              ColumnHeaderStyle="{StaticResource ColBinding}"
     >
    <sdk:DataGrid.Columns >
                        
                        
                        <sdk:DataGridTemplateColumn 
                            CellTemplate="{StaticResource ParticipantCol}" 
                            Header="{Binding Text, ElementName=participantHeader}"
                            Width="1*"  
                            SortMemberPath="ParticipantName"/>
                        
                        
    </sdk:DataGrid.Columns>
    </sdk:DataGrid>
    </Border>
    </Grid>
    </UserControl>
    Also u need a converter.
    namespace ccc.RI.Common.Converters
    {
        public class BindingConverter  : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                if (value.GetType().Name == "Binding")
                {
                    ContentControl cc = new ContentControl();
                    Binding newValue = value as Binding;
                    newValue.Mode = BindingMode.TwoWay;
                    cc.SetBinding(ContentControl.ContentProperty, newValue as Binding);
                    return cc;
                }
                else
                {
                    return value;
                }
            }
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                return null;
            }
        }
    }
    Hope this helps

    I dont remember the link to the article.


    In case I get I can post it.


    Right now I am pasting the code I have


    <UserControl

    x:Class="ccc.RI.SMViewDefault.View.DefaultListView"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" 

    xmlns:conv="clr-namespace:ccc.RI.Common.Converters;assembly=ccc.RI.Common"

    mc:Ignorable="d"

    d:DesignHeight="300" d:DesignWidth="400">

    <UserControl.Resources>

    <conv:BooleanFontConverter x:Key="boofont"></conv:BooleanFontConverter>

            <conv:BindingConverter x:Key="BindCon"/>

            <Style x:Key="ColBinding" TargetType="sdk:DataGridColumnHeader" >

                <Setter Property="ContentTemplate" >

                    <Setter.Value>

                        <DataTemplate>

                            <ContentPresenter Content="{Binding Converter={StaticResource BindCon}}"  />

                        </DataTemplate>

                    </Setter.Value>

                </Setter>

            </Style>

            

            <DataTemplate x:Key="ParticipantCol">

                <Grid>

                    <TextBlock Text="{Binding ParticipantName}" FontWeight="{Binding IsRead,Converter={StaticResource boofont}}" Margin="0,4"

    ></TextBlock>

                </Grid>

            </DataTemplate>

            

    </UserControl.Resources>


    <Grid x:Name="LayoutRoot" HorizontalAlignment="Stretch" Margin="1,0,1,11">

            <TextBox Text="{Binding GetParticipantHeader}" x:Name="participantHeader" />

            

    <Border BorderBrush="#FFA6B6D6" BorderThickness="2" CornerRadius="2"

    x:Name="defaultview">

    <sdk:DataGrid ItemsSource="{Binding Path=GetMessages}" 

     AutoGenerateColumns="False" 

                              ColumnHeaderStyle="{StaticResource ColBinding}"

     >

    <sdk:DataGrid.Columns >

                        

                        

                        <sdk:DataGridTemplateColumn 

                            CellTemplate="{StaticResource ParticipantCol}" 

                            Header="{Binding Text, ElementName=participantHeader}"

                            Width="1*"  

                            SortMemberPath="ParticipantName"/>

                        

                        

    </sdk:DataGrid.Columns>

    </sdk:DataGrid>

    </Border>

    </Grid>

    </UserControl>



    Also u need a converter.


    namespace ccc.RI.Common.Converters

    {

        public class BindingConverter  : IValueConverter

        {


            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

            {

                if (value.GetType().Name == "Binding")

                {

                    ContentControl cc = new ContentControl();

                    Binding newValue = value as Binding;

                    newValue.Mode = BindingMode.TwoWay;

                    cc.SetBinding(ContentControl.ContentProperty, newValue as Binding);

                    return cc;

                }

                else

                {

                    return value;

                }

            }


            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

            {

                return null;

            }

        }

    }



    Hope this helps

    Tuesday, September 21, 2010 8:44 AM