简体   繁体   English

wpf单击按钮后更改列宽(MVVM模式)

[英]wpf change column width after a click on a button (MVVM pattern)

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. 我正在学习MVVM模式,我想避免后面的代码。

I am able to initilaize the width at 0 but i am not succeed to change the width at runtime. 我可以将宽度初始化为0,但是在运行时无法成功更改宽度。

i show you a copy of my code. 我给你看我的代码副本。

Hope you can help me ! 希望你能帮我 !

thanks a lot guy 非常感谢

cheers Cyrille 欢呼西里尔

MainView.xaml 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 MainViewModel用于绑定宽度并将列宽度初始化为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 MainGridModel支持网格的属性

private GridLength notamWidth;

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

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

            notamWidth = value;
        }
    }

RelayCommand for changing the column width RelayCommand用于更改列宽

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

As Daniel mentions in the above comment, you need to implement INotifyPropertyChanged . 正如Daniel在以上评论中提到的那样,您需要实现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. Marc Gravell对这个问题的答案( 实现INotifyPropertyChanged-是否存在更好的方法? )包含了您需要这样做的所有信息。

Also, you need to alter your binding to include Mode and UpdateSourceTrigger (see below): 另外,您需要更改绑定以包括ModeUpdateSourceTrigger (请参见下文):

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

I try to follow your advise. 我尝试听从您的建议。 I update my code to insert InotifyPropertyChanged and also changing the binding property. 我更新代码以插入InotifyPropertyChanged并更改绑定属性。 I'm not able to initialize the column width anymore and button command is still not changing the columndefinition width. 我无法再初始化列宽,并且button命令仍未更改columndefinition宽度。 this make me crazy... 这让我发疯...

MainView.xaml with Resource and updated Binding property 具有资源和更新的Binding属性的MainView.xaml

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 MainGridModel实现InotifyPropertyChanged和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 MainViewModel操纵NotamWidth属性和relayCommand的按钮命令

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)
        };

    }

Like most people have said, you need to have INotifyPropertChanged where you variable is bound to. 就像大多数人所说的那样,您需要在变量绑定到的位置具有INotifyPropertChanged。

xaml: 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. 然后,您需要在xaml.cs的构造函数中定义正确的“ Datacontext”。 For instance, if "NotamWidth" is a variable in your xaml.cs, you would set Datacontext to equal "this". 例如,如果“ NotamWidth”是xaml.cs中的变量,则可以将Datacontext设置为等于“ this”。

xaml.cs: xaml.cs:

Datacontext = this; 

However, say NotamWidth is a variable in another class "GridChanger". 但是,说NotamWidth是另一个类“ 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. 获取正确的Datacontext的一种方法是,在xaml.cs中创建类“ GridChanger”的全局实例,然后使Datacontext等于该实例。

xaml.cs: 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 whereveryourvariableis.cs

private double _NotamWidth;

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

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. 您可以将其设置为“自动”,然后绑定该列的根面板的Width属性,而不是绑定Grid.Column的Width。 After that you can construct your UI inside the root panel. 之后,您可以在根面板中构建UI。

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. 除了将窗口/应用程序的DataContext设置为ViewModel的实例之外,ViewModel中的INotifyPropertyChanged仍然是必须的。

PS:Note that the Grid.Width property is with different type. PS:请注意,Grid.Width属性具有不同的类型。 You should update the type of NotamWidh property in the ViewModel 您应该在ViewModel中更新NotamWidh属性的类型。

Hello and thanks for your answer. 您好,谢谢您的回答。

I try all your proposition. 我会尽你所能。 But I was still enable to change the column width with MVVM pattern. 但是我仍然可以使用MVVM模式更改列宽。 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 西里尔

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM