【问题标题】:How to reload the View in MVVM?如何在 MVVM 中重新加载视图?
【发布时间】:2018-05-22 19:10:22
【问题描述】:
<Style x:Key="ListBoxItemStyle" TargetType="{x:Type ListBoxItem}">
    <Setter Property="Margin" Value="5" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                <Grid
                    Grid.IsSharedSizeScope ="False"
                    HorizontalAlignment="Stretch"
                    VerticalAlignment="Center"
                    ScrollViewer.CanContentScroll="True"
                    ScrollViewer.HorizontalScrollBarVisibility="Visible">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
                    <Grid Grid.Row="0">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <RadioButton
                            Name="RadioButton"
                            Grid.Column="0"
                            Margin="16"
                            VerticalAlignment="Center"
                            IsChecked="False" />
                        <TextBlock
                            Grid.Column="1"
                            HorizontalAlignment="Left"
                            VerticalAlignment="Center"
                            FontFamily="{StaticResource RRWFont}"
                            FontSize="{Binding FontSize, ElementName=TextBlock}"
                            Foreground="{StaticResource DarkGrey}"
                            Text="{Binding Path=Content.Name}"
                            TextAlignment="Left"
                            TextWrapping="Wrap" />
                    </Grid>
                    <Image
                        Grid.Row="1"
                        Width="auto"
                        Height="auto"
                        Source="{Binding Path=Content.File}" />
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter TargetName="RadioButton" Property="IsChecked" Value="True" />
                    </Trigger>
                    <Trigger SourceName="RadioButton" Property="IsChecked" Value="True">
                        <Setter Property="IsSelected" Value="True" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

XAML(列表框)

   <ListBox
        Grid.Column="1"
        HorizontalAlignment="Center"
        Background="{x:Null}"
        BorderBrush="{x:Null}"
        ItemContainerStyle="{StaticResource ListBoxItemStyle}"
        ItemsSource="{Binding Path=AnswersVariants}"
        ScrollViewer.HorizontalScrollBarVisibility="Disabled"
        SelectedItem="{Binding Path=SelectAnswer, Mode=TwoWay}"
        SelectionMode="Single">

        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel
                    HorizontalAlignment="Center"
                    VerticalAlignment="Center"
                    Loaded="ListBoxWrapPanel_Loaded"
                    Orientation="Horizontal" />
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>

C#

private void ListBoxWrapPanel_Loaded(object sender, RoutedEventArgs e)
{
    if (!(sender is WrapPanel panel))
        return;
    if (panel.Children.Count == 0)
        return;

    var max = (from FrameworkElement panelChild in panel.Children
            select panelChild.ActualWidth + panelChild.Margin.Left + panelChild.Margin.Right)
        .Concat(new double[] { 0 }).Max();
    panel.ItemWidth = max;
}

我有这个 ContentControl:(类名已更改)

*XAML:*
ContentControl
            Content="{Binding CurrentContent}"
 I change the CurrentContent like this:

CurrentContent = new ContentOne();
CurrentContent = new ContentTwo();

为 MVVM 创建了 INotifyPropertyChanged 等,并且一切正常 正确。

有这样的问题。当一个 CurrentContent 更改为另一个时, 但同一个类,视图没有改变,它只改变了 数据。

那些。

CurrentContent = new ContentOne(); //1
---over time
CurrentContent = new ContentOne(); //2

在第二种情况下,视图保持不变。

这会导致一个问题,因为在View中有一个ListBox,ItemPanel 它代表 WrapPanel。对于所有 WP 儿童,身高和 宽度是相同的,并在视图的初始化过程中设置 通过找到最大的宽度和高度。当 ViewModel 变化,但视图不变,可能会发生以下情况:

查看 *1:

查看 *2:

您将无法重新计算高度和宽度,因为它们 当它们尚未为 WrapPanel 设置时,将被考虑,并且在 * 2 的情况下,它们已经设置好了。

附:在这种情况下,一切正常:

CurrentContent = new ContentOne();
---over time
CurrentContent = new ContentTwo();
---over time
CurrentContent = new ContentOne();

【问题讨论】:

  • “高度和宽度是相同的,并且是在 View 的初始化过程中通过查找最大宽度和高度来设置的” -- 您的 XAML 已损坏。不要那样设置宽度和高度。您后面的代码应该完全没有用于布局、对齐、宽度等的代码。您可以使用 WPF 布局技术(如 Grids、Horizo​​ntalAlignment、VerticalAlignment 等)来完成所有这些工作,因此它会在需要时自动更新。如果您向我们展示有问题的 XAML,我们可以帮助您修复它,这样就不会出现问题。
  • 如果您绝对无法编写正确的 XAML,请创建一个 DataContextChanged 事件处理程序并从那里调用您的布局代码。
  • 请发布您的实际代码。你在寻求帮助,但你每一步都在与我作斗争。
  • 我找到了解决方案。您需要使用 UniformGrid,而不是 WrapPanel。更感谢你,尽管我的不足,你试图帮助我! :-)
  • 太棒了!在 WPF 中,几乎总有一种简单的方法可以让布局按照您的意愿行事,而无需任何代码。

标签: c# wpf mvvm reload


【解决方案1】:

您需要使用 UniformGrid,而不是 WrapPanel。

【讨论】:

    猜你喜欢
    • 2018-12-24
    • 2012-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-29
    • 2015-08-29
    • 1970-01-01
    相关资源
    最近更新 更多