0

i try to change the column width after a click on a button.

I am learning MVVM pattern and I want to avoid code behind.

I am able to initilaize the width at 0 but i am not succeed to change the width at runtime.

i show you a copy of my code.

Hope you can help me !

thanks a lot guy

cheers Cyrille

MainView.xaml

<Grid.ColumnDefinitions>
     <ColumnDefinition Width="10"/>
     <ColumnDefinition Width="{Binding NotamWidth}"/>
     <ColumnDefinition Width="*"/>
     <ColumnDefinition Width="10"/>
</Grid.ColumnDefinitions>

MainViewModel for binding the width and to initialize the column width at 0

//Propoerty for column width
public GridLength NotamWidth { get; set; }
public AirportViewModel()
{
   //initialize width of column at 0
   MainGridModel MainGridModel = new MainGridModel(new GridLength(0));
   this.NotamWidth = MainGridModel.NotamWidth;
 }

MainGridModel which support property for the grid

private GridLength notamWidth;

    public MainGridModel(GridLength width)
    {
        NotamWidth = width;
    }

    public GridLength NotamWidth
    {
        get
        {
            return notamWidth;
        }
        set {

            notamWidth = value;
        }
    }

RelayCommand for changing the column width

public void ShowNotamExecute(object parameter)
{
 //Masque la colonne notam            
 this.NotamWidth = new GridLength(400);
 }
aviateur22
  • 45
  • 1
  • 8

5 Answers5

0

As Daniel mentions in the above comment, you need to implement INotifyPropertyChanged. The answer by Marc Gravell on this question (Implementing INotifyPropertyChanged - does a better way exist?) contains all the information you should need to do so.

Also, you need to alter your binding to include Mode and UpdateSourceTrigger (see below):

<Grid.ColumnDefinitions>
     <ColumnDefinition Width="10"/>
     <ColumnDefinition Width="{Binding NotamWidth, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
     <ColumnDefinition Width="*"/>
     <ColumnDefinition Width="10"/>
</Grid.ColumnDefinitions>
0

I try to follow your advise. I update my code to insert InotifyPropertyChanged and also changing the binding property. I'm not able to initialize the column width anymore and button command is still not changing the columndefinition width. this make me crazy...

MainView.xaml with Resource and updated Binding property

xmlns:mw="clr-namespace:WpfAppEssaisMVVM.Model.Windows"

<Window.Resources>
    <!--Instance of mainGridModel -->
    <mw:MainGridModel x:Key="MainGridModel"/>
</Window.Resources>

<Grid.ColumnDefinitions>
        <ColumnDefinition Width="10"/>
        <ColumnDefinition Width="500" />
        <ColumnDefinition Width="{Binding Source={StaticResource MainGridModel},Path=NotamWidth, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="10"/>
    </Grid.ColumnDefinitions> 

MainGridModel implementing InotifyPropertyChanged and Binding ColumnDefinition

    private GridLength notamWidth;

    public GridLength NotamWidth
    {
        get
        {
            return notamWidth;
        }
        set
        {
            notamWidth = value;
            OnPropertyChanged("NotamWidth");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string PropertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
    }

MainViewModel manipulating the NotamWidth Property and relayCommand for button command

public MainViewModel()
    {
        //Initialize the column to gridlength 0
        MainGridModel MainGridModel = new MainGridModel
        {
            NotamWidth = new GridLength(0)
        };
     }
//Action on button command
public void ShowNotamExecute(object parameter)
    {
       //set the column Width
        MainGridModel MainGridModel = new MainGridModel
        {
            NotamWidth = new GridLength(400)
        };

    }
aviateur22
  • 45
  • 1
  • 8
0

Like most people have said, you need to have INotifyPropertChanged where you variable is bound to.

xaml:

<Grid.ColumnDefinitions>
 <ColumnDefinition Width="10"/>
 <ColumnDefinition Width="{Binding NotamWidth, UpdateSourceTrigger=PropertyChanged}"/>
 <ColumnDefinition Width="*"/>
 <ColumnDefinition Width="10"/>

You then need to have the correct "Datacontext" defined within your constructor for xaml.cs. For instance, if "NotamWidth" is a variable in your xaml.cs, you would set Datacontext to equal "this".

xaml.cs:

Datacontext = this; 

However, say NotamWidth is a variable in another class "GridChanger". One way you can get the correct Datacontext is by creating a global instance of the class "GridChanger" within your xaml.cs, then making Datacontext equal to the instance.

xaml.cs:

public class MainWindow 
{
    GridChanger gChng = new GridChanger();

    public MainWindow()
    {
        DataContext = gChng;
    }
}

From there we can create the variable we'll bind to. There may be a better way to do this, but I've always made variables that I bind this way.

whereveryourvariableis.cs

private double _NotamWidth;

public double NotamWidth
{
    get
    {
        return _NotamWidth;
    }
    set
    {
        _NotamWidth = value;
        if (PropertyChanged != null)
        {
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(NotamWidth)));
        }
    }
}
Aaron
  • 97
  • 12
0

Instead of binding the Width of the Grid.Column, you can set it to Auto and then bind the Width property of the root panel for that column. After that you can construct your UI inside the root panel.

Here is the structure I suggest:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="10"/>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="10"/>
    </Grid.ColumnDefinitions>
    ...
    <Grid Grid.Column="1" x:Name="myRootPanelForColumn1" Width="{Binding NotamWidth}">

    </Grid>
    ...
</Grid>

INotifyPropertyChanged in your ViewModel remains a must as well as setting the DataContext of your window/application to be an instance of your ViewModel.

P.S.:Note that the Grid.Width property is with different type. You should update the type of NotamWidh property in the ViewModel

Pavel Pavlov
  • 697
  • 2
  • 9
  • 18
0

Hello and thanks for your answer.

I try all your proposition. But I was still enable to change the column width with MVVM pattern. I finally decided to go with code behind. I will try again later to avoid this solution

Grid definition

<Grid.ColumnDefinitions>
  <ColumnDefinition Width="10"/>
  <ColumnDefinition Width="600" />
  <ColumnDefinition Width="0"/> <-- Column hide at initiliasition--!>
  <ColumnDefinition Width="*"/>
  <ColumnDefinition Width="10"/>
< /Grid.ColumnDefinitions>

button with the click event

<Button Name="AirportButton
  Click="AirportButton_Click"
  Height="30"
</Button>

Click event to show the column.

   private void AirportButton_Click(object sender, RoutedEventArgs e)
    {
        //Set the column width at 500 after a click on the button);
        MainWindow.ff.ColumnDefinitions[2].Width = new GridLength(500);


    }

i will keep my code update when i found a solution

Cyrille

aviateur22
  • 45
  • 1
  • 8