【问题标题】:How to change the visibility from a stackpanel in a splitview from another class如何从另一个类的拆分视图中更改堆栈面板的可见性
【发布时间】:2018-11-26 11:00:32
【问题描述】:

我想将堆栈面板的可见性从 visibility.Collapsed 更改为 visibility.visible。但我不能在它所在的主页上做到这一点。那是因为您需要在应用程序中登录,所以我想在 Homepage.cs 中执行此操作,但是如何从那里更改堆栈面板的值?我需要这样做,因为我所有的视图都加载在框架中,您可以在下面的代码中看到。

下面是拆分视图的代码

<SplitView x:Name="mySplitView" IsPaneOpen="False" DisplayMode="CompactInline">
    <SplitView.Pane>
        <StackPanel Background="Gray" Tapped="StackPanel_Tapped">
            <Button FontFamily="Segoe MDL2 Assets" Content="&#xE700;" Click="Menu_Button_Click" Width="50" Height="50"  />
            <StackPanel Orientation="Horizontal" Tapped="Home_StackPanel_Tapped">
                <Button FontFamily="Segoe MDL2 Assets" Content="&#xE80F;" Width="50" Height="50" />
                <TextBlock Text="Home" FontSize="18" VerticalAlignment="Center" Margin="5,0,0,0"/>
            </StackPanel>
            <Line X1="0" X2="0" Y1="5" Y2="5" StrokeThickness="1.5" Stretch="UniformToFill" Height="10" />
            <StackPanel Orientation="Horizontal" Tapped="Company_StackPanel_Tapped" Visibility="Collapsed">
                <Button FontFamily="Segoe MDL2 Assets" Content="&#xE731;" Width="50" Height="50"/>
                <TextBlock Text="Bedrijven" FontSize="18" VerticalAlignment="Center" Margin="5,0,0,0"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal" Tapped="Event_StackPanel_Tapped" Visibility="Collapsed">
                <Button FontFamily="Segoe MDL2 Assets" Content="&#xE787;" Width="50" Height="50"/>
                <TextBlock Text="Evenementen" FontSize="18" VerticalAlignment="Center" Margin="5,0,0,0"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal" Tapped="Promo_StackPanel_Tapped" Visibility="Collapsed">
                <Button FontFamily="Segoe MDL2 Assets" Content="&#xE8EC;" Width="50" Height="50" />
                <TextBlock Text="Promoties" FontSize="18" VerticalAlignment="Center" Margin="5,0,0,0"/>
            </StackPanel>
            <Line X1="0" X2="0" Y1="5" Y2="5" StrokeThickness="1.5" Stretch="UniformToFill" Height="10"/>
            <StackPanel Orientation="Horizontal" Tapped="Login_StackPanel_Tapped">
                <Button FontFamily="Segoe MDL2 Assets" Content="&#xE77B;" Width="50" Height="50" />
                <TextBlock Text="Inloggen" FontSize="18" VerticalAlignment="Center" Margin="5,0,0,0"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal" Tapped="Registreer_StackPanel_Tapped" >
                <Button FontFamily="Segoe MDL2 Assets" Content="&#xE8FA;" Width="50" Height="50" />
                <TextBlock Text="Registreren" FontSize="18" VerticalAlignment="Center" Margin="5,0,0,0"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal" x:Name="profielwijzigen" Tapped="Profiel_Wijzigen_StackPanel_Tapped" Visibility="Collapsed">
                <Button FontFamily="Segoe MDL2 Assets" Content="&#xE713;" Width="50" Height="50" />
                <TextBlock Text="Profiel Wijzigen" FontSize="18" VerticalAlignment="Center" Margin="5,0,0,0"/>
            </StackPanel>
        </StackPanel>
    </SplitView.Pane>
    <SplitView.Content>
        <Frame Name="mainFrame">
            Wait for redirect
        </Frame>
    </SplitView.Content>
</SplitView>

【问题讨论】:

  • 您应该研究绑定 - 在您背后的代码中,您应该绑定到一些属性,这些属性封装了登录状态或任何决定堆栈面板可见性的属性。
  • 你可以开始使用一点 MVVM。然后某些虚拟机只需要绑定两个属性:一个用于设置,另一个用于读取和更改可见性(通过数据触发器或转换器)。如果您想要仅查看解决方案,那么您可以使用常见的RelativeSource AncestorType parent 并使用其属性之一(Tag? 如果这不起作用,自定义附加属性将)。在一个项目中,我为嵌套用户控件的一些复杂布局创建了一个自定义面板类 public class MyGrid: Grid { }
  • 刚刚检查过,RelativeSource 不能在 Frame.Content 中工作。您必须使用代理或更好的 - 使用 MVVM 方法。
  • 不使用框架和页面的众多原因之一。您应该在其中使用内容控件和用户控件。

标签: c# wpf


【解决方案1】:

如果您开始使用 MVVM,这些任务将非常容易。下面是一个例子(作为一种介绍)。

对于每个不同的视图(UserControl、数据模板、窗口等),您必须创建一个视图模型 (VM)。视图模型可以有复杂的关系。让我们创建一个:

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    void OnPropertyChanged([CallerMemberName] string property = null) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));


    bool _show;
    public bool Show
    {
        get { return _show; }
        set
        {
            _show = value;
            OnPropertyChanged();
        }
    }
}

通常会有更多属性,它们将专用于处理特定视图(例如,主窗口中的所有内容或某些用户控件),但目前让我们保持简单。

接下来让我们重新创建您的问题:我们将有 StackPanelFrame。框架部分将具有 CheckBox 用于通过绑定到 bool 属性来更改可见性。 StackPanel 将有一些文本(以查看它是否有效)并将可见性绑定到相同的 bool 属性。

<Window ... >
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="converter"/>
        <local:ViewModel x:Key="vm"/>
    </Window.Resources>
    <StackPanel>
        <StackPanel Visibility="{Binding Show, Converter={StaticResource converter}}" DataContext="{StaticResource vm}">
            <TextBlock Text="Some test"/>
        </StackPanel>
        <Frame>
            <Frame.Content>
                <CheckBox IsChecked="{Binding Show}" DataContext="{StaticResource vm}"/>
            </Frame.Content>
        </Frame>
    </StackPanel>
</Window>

MVVM 的整个想法是利用DataContext 继承:任何嵌套的框架元素都将从其父级获取上下文。但在本例中,它是直接为每个设置的。

视图模型的实例是在 windows 资源中创建的。您可能需要在应用程序级别使用它,甚至可能需要传递它(不确定您的框架内容是什么样子的)。

转换器用于将bool转换为Visibility

如果你运行它,你应该会看到如下内容:

【讨论】:

  • 这是可行的,但我的问题是我不想更改另一个类中的可见性值,该类不是该 xaml 的类,而是来自另一个 xaml,我不知道该怎么做那
【解决方案2】:

您可以使用一些事件

在用于登录的子组件(比如类是LoginControl)中声明事件:

public event EventHandler LoggedIn = delegate {};

您在主组件中注册一个处理程序:

loginControl.LoggedIn += (s, e) => {
    Company_StackPanel.Visibility = Visibility.Visible;
    Event_StackPanel.Visibility = Visibility.Visible;
    Promo_StackPanel.Visibility = Visibility.Visible;
};

在您的LoginControl 中,当用户登录时,您会引发事件:

this.LoggedIn(this, EventArgs.Empty);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多