Set property of ViewModel using setter within some

2019-09-13 04:02发布

问题:

I tried to google but all problems had related heading but problem context different. My problem is that I have a DataTrigger which gets triggered when certain property has a certain value i-e IsDockPanelVisible has true/false (different triggers for each value) in my case. Now when it gets triggered, it should set the value of Width - a property defined in ViewModel. Here is my specific code:

<Style.Triggers>
            <DataTrigger Binding="{Binding IsDockPanelVisible}" Value="False">
                <Setter Property="mainWindowViewModel.Width" Value="Auto">
                </Setter>
            </DataTrigger>
            <DataTrigger Binding="{Binding IsDockPanelVisible}" Value="True">
                <Setter Property="mainWindowViewModel.Width" Value="7*"></Setter>
                <Setter Property="MinWidth">
                    <Setter.Value>
                        <MultiBinding Converter="{StaticResource StringSumtoIntConvert}">
                            <Binding ElementName="cdLblNotificationsHeader" Path="MinWidth"/>
                            <Binding ElementName="cdBtnNotificationsClose" Path="ActualWidth"/>
                        </MultiBinding>
                    </Setter.Value>
                </Setter>
            </DataTrigger>
</Style.Triggers>

Here is complete code:

<Window x:Class="EmbroidaryManagementSystem_V2._0.View.MainWindow"
    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:local="clr-namespace:EmbroidaryManagementSystem_V2._0.View"
    xmlns:adf="clr-namespace:EmbroidaryManagementSystem_V2"
    xmlns:collectionVM="clr-namespace:EmbroidaryManagementSystem_V2._0.ViewModel.CollectionsViewModel"
    xmlns:helperClasses="clr-namespace:EmbroidaryManagementSystem_V2._0.HelperClasses"
    xmlns:mainWindowVM="clr-namespace:EmbroidaryManagementSystem_V2._0.ViewModel.UIViewModel"
    mc:Ignorable="d"
    Title="Khalil Embroidery Management System" Height="655.512" Width="1135.159" FontSize="24" 
    WindowStartupLocation="CenterScreen" MinWidth="200" MinHeight="300" 
    Icon="/EmbroidaryManagementSystem V2.0;component/Images/KhalilEmbroideryLogonobackgrnd2.png"
    >
<Window.DataContext>
    <!--<collectionVM:ClientCollectionVM/>-->
    <mainWindowVM:MainWindowViewModel/>
</Window.DataContext>
<Window.Resources>
    <helperClasses:StringSumtoIntConverter x:Key="StringSumtoIntConvert"/>
    <ControlTemplate x:Key="DockedPanelButtonTemplate" TargetType="{x:Type Button}">
        <ControlTemplate.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Background" Value="Black"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

    <Style x:Key="DockedPanelButton" TargetType="Button">
        <Setter Property="LayoutTransform">
            <Setter.Value>
                <RotateTransform Angle="90"/>
            </Setter.Value>
        </Setter>
        <!--<Setter Property="Template" Value="{StaticResource DockedPanelButtonTemplate}"/>-->
        <Setter x:Name="border" Property="BorderBrush" Value="DodgerBlue"/>
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="BorderBrush" Value="Aquamarine"/>
                <Setter Property="Background" Value="Yellow"/>
            </Trigger>
        </Style.Triggers>
    </Style>

    <!--<mainWindowVM:MainWindowViewModel x:Key="WindowViewModel"/>-->
    <Style x:Key="OnIsDockPanelVisibleChangedGridBehaviour" TargetType="Grid">
        <Style.Triggers>
            <DataTrigger Binding="{Binding IsDockPanelVisible}" Value="False">
                <Setter Property="Visibility" Value="Collapsed"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding IsDockPanelVisible}" Value="True">
                <Setter Property="Visibility" Value="Visible"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>

    <Style x:Key="OnIsDockPanelVisibleChangedPanelColumnBehaviour" TargetType="ColumnDefinition">
        <Style.Triggers>
            <DataTrigger Binding="{Binding IsDockPanelVisible}" Value="False">
                <Setter Property="mainWindowViewModel.Width" Value="Auto">
                </Setter>
            </DataTrigger>
            <DataTrigger Binding="{Binding IsDockPanelVisible}" Value="True">
                <Setter Property="mainWindowViewModel.Width" Value="7*"></Setter>
                <Setter Property="MinWidth">
                    <Setter.Value>
                        <MultiBinding Converter="{StaticResource StringSumtoIntConvert}">
                            <Binding ElementName="cdLblNotificationsHeader" Path="MinWidth"/>
                            <Binding ElementName="cdBtnNotificationsClose" Path="ActualWidth"/>
                        </MultiBinding>
                    </Setter.Value>
                </Setter>
            </DataTrigger>
        </Style.Triggers>
    </Style>

    <Style x:Key="OnIsDockPanelVisibleChangedButtonBehaviour" TargetType="Button" 
           BasedOn="{StaticResource DockedPanelButton}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding IsDockPanelVisible}" Value="True">
                <Setter Property="Visibility" Value="Collapsed"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding IsDockPanelVisible}" Value="False">
                <Setter Property="Visibility" Value="Visible"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>

    <Style x:Key="OnIsDockPanelVisibleChangedGridSplitterBehaviour" TargetType="GridSplitter">
        <Style.Triggers>
            <DataTrigger Binding="{Binding IsDockPanelVisible}" Value="True">
                <Setter Property="Visibility" Value="Visible"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding IsDockPanelVisible}" Value="False">
                <Setter Property="Visibility" Value="Collapsed"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>

    <SolidColorBrush x:Key="TransparentBackground">
        Transparent
    </SolidColorBrush>

    <Style x:Key="LeftDockedPanelButton" TargetType="Button" BasedOn="{StaticResource OnIsDockPanelVisibleChangedButtonBehaviour}">
        <Setter Property="BorderThickness" Value="0,0,0,15"/>
    </Style>

    <Style x:Key="RightDockedPanelButton" TargetType="Button" BasedOn="{StaticResource OnIsDockPanelVisibleChangedButtonBehaviour}">
        <Setter Property="BorderThickness" Value="0,8,0,0"/>
    </Style>

    <BitmapImage x:Key="LogoImage" UriSource="/Images/KhalilEmbroideryLogonobackgrnd2.png"/>
</Window.Resources>

<!--<ScrollViewer HorizontalScrollBarVisibility="Auto">-->
<Grid x:Name="mainGrid" Background="#FFD6DBE9">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition MinHeight="103"/>
    </Grid.RowDefinitions>

    <Menu Height="18" VerticalAlignment="Top" Grid.Row="0" Margin="0,0,0,0">
        <MenuItem Header="_Exit">
            <MenuItem Header="Exit"/>
        </MenuItem>
        <MenuItem Header="_View">
            <MenuItem Header="Notifications" Command="{Binding ShowDockPanelCommand}"/>
        </MenuItem>
        <MenuItem Header="Add _New">
            <MenuItem Header="Employee"/>
            <MenuItem Header="Employee Salary"/>
        </MenuItem>
        <MenuItem Header="_About">
            <MenuItem Header="About us"/>
        </MenuItem>
    </Menu>
    <ScrollViewer HorizontalScrollBarVisibility="Auto" Grid.Row="1">
        <Grid x:Name="innerContentGrid" MinHeight="500" MinWidth="600">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="20*" MinWidth="{Binding MinWidth, ElementName=tabDataEntities}"/>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Style="{StaticResource OnIsDockPanelVisibleChangedPanelColumnBehaviour}" Width="{Binding }"/>
            </Grid.ColumnDefinitions>

            <GridSplitter x:Name="gridSplitter" Grid.Column="1" HorizontalAlignment="Center" 
                          Width="3" Margin="0,10,0,0" Background="#FF657695" 
                          Style="{StaticResource OnIsDockPanelVisibleChangedGridSplitterBehaviour}"/>

            <Grid x:Name="gridNotificationsHeader" Grid.Column="2" Background="#FF657695" Margin="0,10,0,0" 
                  Height="30" VerticalAlignment="Top" Style="{StaticResource OnIsDockPanelVisibleChangedGridBehaviour}">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition x:Name="cdLblNotificationsHeader" 
                                      MinWidth="{Binding Width, ElementName=lblNotificationsHeader}"/>
                    <ColumnDefinition x:Name="cdBtnNotificationsClose" Width="Auto"/>
                </Grid.ColumnDefinitions>
                <Label x:Name="lblNotificationsHeader" Content="Notifications" VerticalAlignment="Top" 
                    FontSize="14.667" Height="29" Foreground="#FFEBF0EE" HorizontalAlignment="Left" Width="92"/>
                <Button x:Name="btnNotificationsClose" Content="X" 
                    Margin="0,5,8,0" VerticalAlignment="Top" Width="20" FontFamily="Verdana" HorizontalAlignment="Right" 
                        Background="Transparent" FontSize="13.333" Foreground="Black" Grid.Column="1"
                        Command="{Binding HideDockPanelCommand}"/>
            </Grid>
            <TabControl Grid.Column="0" x:Name="tabDataEntities" Margin="0,10,5,0" FontSize="12"
                    MinWidth="{Binding ElementName=TabItemOne, Path=ActualWidth}">
                <TabItem x:Name="TabItemOne">
                    <TabItem.Header>Tab Item</TabItem.Header>
                    <Grid Background="#FFE5E5E5" Margin="0,0,0,0"/>
                </TabItem>
                <TabItem Header="TabItem">
                    <Grid Background="#FFE5E5E5"/>
                </TabItem>
            </TabControl>
            <Button x:Name="btnShowNotificationsPanel" Content="Notifications" Grid.Column="2"
                    Margin="0,12,-0,0" VerticalAlignment="Top" Style="{StaticResource RightDockedPanelButton}" Background="Transparent"
                    FontSize="12" Height="Auto" HorizontalAlignment="Right" Width="Auto" 
                    Command="{Binding ShowDockPanelCommand}"/>
        </Grid>
    </ScrollViewer>
</Grid>

Width is property in my ViewModel and not FrameworkElement.Width. However, it has the same double type. ViewModel class is MainWindowViewModel and its object in XAML is mainWindowVM.

回答1:

You can not set view model properties with a setter of your view.

Have a look here: Setter.Property Property.

It states that you can only uses a DependencyProperty as the value for the setter (Besides, you cannot specify a binding expression there, just a string value).

<object Property="DependencyProperty" .../>


Suggestion:

If IsDockPanelVisible is a property inside your view model, you could react to change events there in your view model, either by subscribing to INotifyPropertyChanged of this property or by calling a method in the setter of IsDockPanelVisible.

You could then set another property in your view model which is bound to the view and then achieve your desired result.