WPF MVVM Light - 关于视图通信

时间:2014-07-14 19:56:33

标签: wpf xaml mvvm mvvm-light

我目前正致力于一个工作项目。我正在寻求外部设计意见,以及有关我所面临问题的一​​些一般信息。

我们有一个MainWindow.xaml文件,位于项目的根目录中。在这个主窗口中是一些折叠堆栈面板,功能区工具栏等的设计和逻辑。

到目前为止,我们的想法是在每个堆栈面板中包含一个不同的内容,以帮助使代码整洁。这些观点位于“观看次数”中。夹。所以为了清楚起见,MainWindow.xaml和其他视图不在同一目录中。如有必要,这可以改变。

所以这是我的问题/问题:我们有一个窗口(' A'),一个带有可折叠堆栈面板的主面板,其中包含一些信息(' B')在窗口' A'。然后还有另一个堆栈面板来管理' B'(崩溃/可见)(' C')中的内容。

' A'包含一个切换按钮,用于显示/折叠' B'。 ' B'包含一个按钮,用于显示/折叠' C'。 ' C'包含一个显示/折叠的按钮,' C'。

' C' 的逻辑应包含在视图中,因此MainWindow(' A')应该有一个简单的标记:

<StackPanel Style="{StaticResource FrameGradient}"  Tag="{Binding ElementName=ToggleButton}">
    <view:Content></view:Content>
</StackPanel>

目前,用于切换&#39; A&#39;内的按钮的绑定在造型。在这种情况下,FrameGradient有这样的触发器:

<Style x:Key="FrameGradient" TargetType="{x:Type StackPanel}">
    //Setter properties
    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=Tag.IsChecked, RelativeSource={RelativeSource Self}}" Value="False">
            <Setter Property="StackPanel.Visibility" Value="Collapsed" />
        </DataTrigger>
        <DataTrigger Binding="{Binding Path=Tag.IsChecked, RelativeSource={RelativeSource Self}}" Value="True">
            <Setter Property="StackPanel.Visibility" Value="Visible" />
        </DataTrigger>
    </Style.Triggers>
</Style>    

是否有可能在内容&#39;查看切换面板,&#39; C&#39;,哪个不在视图中?我觉得我在这里错过了XAML的核心思想。我找到了一个便宜的&#39;周围的工作是关闭&#39;关闭&#39;来自标签外部内容视图的按钮,但这会导致样式问题,我觉得我不应该做那样愚蠢的事情。同样,我们的想法是Stack Panel的切换按钮&#39; C&#39;包含在另一个视图中,我希望能够从另一个视图切换它。

如果我不够清楚,我会道歉,如果需要,我会向谁提供更多信息。

更新 我有时间实际添加我正在使用的代码,以便更有意义。

MainWindow.xaml - 过滤器逻辑面板(位于根目录中)

    <StackPanel Grid.Row="1" Grid.Column="4" Visibility="Collapsed" Style="{StaticResource FrameGradient}">
        <Grid x:Name="FilterContentGrid">
            <Grid.RowDefinitions>
                <RowDefinition Height="*"></RowDefinition>
            </Grid.RowDefinitions>
            <view:Filters></view:Filters>
        </Grid>
    </StackPanel>

Filters.xaml - 过滤器逻辑视图(位于/视图中) 文件中需要折叠上面的StackPanel的按钮。

<Button x:Name="FilterManagementCloseButton" Content="CLOSE"></Button>

Theme.Xaml - 所有样式的逻辑(位于root,与MainWindow.xaml和App.xaml一起) 按钮样式

<Style x:Key="FilterManagementCloseButton" TargetType="Button">
    <Setter Property="Padding" Value="10,5,20,3" />

    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=Tag.IsChecked, RelativeSource={RelativeSource AncestorType={x:Type Local:MainWindow}}}" Value="True">
            <Setter Property="StackPanel.Visibility" Value="Visible" />
        </DataTrigger>
    </Style.Triggers>
</Style>

最后,FrameGradient Styling也位于Theme.xaml

<Style x:Key="FrameGradient" TargetType="{x:Type StackPanel}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=Tag.IsChecked, RelativeSource={RelativeSource Self}}" Value="False">
            <Setter Property="StackPanel.Visibility" Value="Collapsed" />
        </DataTrigger>
        <DataTrigger Binding="{Binding Path=Tag.IsChecked, RelativeSource={RelativeSource Self}}" Value="True">
            <Setter Property="StackPanel.Visibility" Value="Visible" />
        </DataTrigger>
    </Style.Triggers>
</Style>

所以,我希望这会让事情更清楚。我希望Filters.xaml中的CLOSE按钮能够折叠位于MainWindow中的堆栈面板。我意识到这段代码现在很乱。

2 个答案:

答案 0 :(得分:1)

  

是否有可能在'内容'视图中切换面板'C',   哪个不在视图中?

创建一个共享VM,每个其他VM将拥有一个可以访问的属性。可以在其他VM的初始化期间加载该VM。为了允许发生更改,将INotifyProperty(ies)放在共享VM上,然后在所有视图中标记所需的逻辑。最后将目标控件正常绑定到datacontext,除了进入共享VM目标属性的子路径。

因此,当一个视图切换(双向绑定)共享属性时,它会反映在目标面板的视图中。

更新示例

这里的想法是为AppPage创建一个viewmodel。该VM将保存在所有视图模型中共享的通用标志。随后创建的每个ViewModel都将引用AppPage的viewmodel。

下面的示例是一个主页,其中AppVM包含一个标志,通知主页是否正在进行登录。如果是,且该值为true,则将启用主页上的绑定按钮。

enter image description here

随后主页可以覆盖appvm,并通过一个有界的复选框在该标志中放置一个新值,该复选框可以直接更改按钮是否已启用;从而改变过程中所有其他VM的标志。

这是Mainpage VM,对于这个例子,我只是创建AppVM,但它可以传入,或从其他地方的静态引用获取。另请注意AV s(appVM)属性更改时我不在乎的方式;这个例子不需要它(我们没有将任何东西绑定到AppVM,只是它需要监视的属性)。

public class MainVM : INotifyPropertyChanged
{
    public AppVM AV { get; set; }

     public MainVM()
     {
        AV = new AppVM() { LoginInProcess = true };
     }
}

这是AppVm

   public class AppVM : INotifyPropertyChanged 
    {
        private bool _LoginInProcess;

        public bool LoginInProcess
        {
            get {  return _LoginInProcess; }
            set { _LoginInProcess = value; OnPropertyChanged(); }
        }
}

这是MainPage的Xaml,其中datacontext已设置为MainVM的实例:

<StackPanel Orientation="Vertical">
    <CheckBox Content="Override"
              IsChecked="{Binding AV.LoginInProcess, Mode=TwoWay}"/>

    <Button Content="Login"
            IsEnabled="{Binding AV.LoginInProcess}"
            Width="75" />

</StackPanel>

我将MVVM基于我的博客文章Xaml: ViewModel Main Page Instantiation and Loading Strategy for Easier Binding,它解释了此示例中其他缺少的项目,例如主页的datacontext加载。

答案 1 :(得分:0)

您可以使用RelativeSource Binding将子视图绑定到父视图模型中的属性。假设您在ToggleButton中有一个MainWindow.xaml,它是绑定到名为IsChecked的属性的数据,该属性在绑定到{{1}的数据的对象中声明属性。您可以使用MainWindow DataContext从任何子视图绑定到同一属性的数据,如下所示:

RelativeSource Binding