Note: Forums will be making significant UX changes to address key usability improvements surrounding search, discoverability and navigation. To learn more about these changes please visit the announcement which can be found HERE.

Answered DataGrid Column Header text change from ViewModel

  • Monday, September 13, 2010 4:15 PM
     
     

    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


All Replies

  • Monday, September 13, 2010 4:57 PM
     
     

    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 5:26 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:40 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 

  • Tuesday, September 14, 2010 12:42 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 2:00 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/ 

  • Monday, September 20, 2010 8:15 PM
     
     Answered

    Thanks

    I found another article  ...

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

  • Monday, September 20, 2010 10:01 PM
     
     

    Would you mind posting the link of that article here to share with other communites.

  • Tuesday, September 21, 2010 8:44 AM
     
     Answered

    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