wpf - 创建一个方形用户控件

标签 wpf user-controls grid microsoft-metro winrt-xaml

我正在设计一个用户控件,它需要是方形的,并填充给定的尽可能多的空间(为了提供一些上下文,它是一个棋盘)。

我的用户控件如下所示:

<Grid>
    <!-- My 8 lines / colums, etc. , sized with "1*" to have equal lines -->
</Grid>

现在我只想说“无论它要扩展什么空间,这个网格都必须是正方形的”。

尝试了徒劳的解决方案:

  1. 我无法使用 UniformGrid,因为我实际上还有行和列的名称,因此我有一个不同大小的前导标题行和列。

  2. 如果我将 ViewboxUniform 结合使用,一切都会变得困惑。

  3. 我尝试使用经典

    <Grid Height="{Binding RelativeSource={RelativeSource Self}, Path=Width}"> ... </Grid>
    

但只有当我手动设置 Width 属性时它才有效。否则,该约束将被忽略。

结论

我不知道,我真的很想避免手动设置 Width/Height ,因为此控件可能会在许多不同的地方使用( ListItem 模板、游戏等...)。


建议的解决方案:

有一些隐藏代码的解决方案。我没有找到仅 XAML 的解决方案。

网格现在是:

<Grid SizeChanged="Board_FullControlSizeChanged">...</Grid>

事件处理程序是:

private void Board_FullControlSizeChanged(object sender, SizeChangedEventArgs args)
{
    double size = Math.min (args.NewSize.Height, args.NewSize.Width);
    ((Grid)sender).Width = size;
    ((Grid)sender).Height = size;
}

最佳答案

我最初尝试修改对 ActualWidth 的绑定(bind),但当 Grid 是顶级元素时它仍然不起作用,并且在某些情况下最终会进一步扩展控件比可用尺寸。因此尝试了一些其他方法来获取所需的输出。

有两种方法可以解决这个问题:

因为这是一个与 View 相关的问题(不破坏 MVVM,保持方形结构,如果你同意有一些代码隐藏,你可以做类似的事情)

private void OnSizeChanged(object sender, SizeChangedEventArgs e) {
  double minNewSizeOfParentUserControl = Math.Min(e.NewSize.Height, e.NewSize.Width);
  mainGrid.Width = minNewSizeOfParentUserControl;
  mainGrid.Height = minNewSizeOfParentUserControl;
}

在您的 xaml 中,您可以将主顶级网格命名为“mainGrid”,并将 UserControl 大小更改事件处理程序附加到上述函数而不是 Grid 本身。

但是,如果您出于某种原因完全讨厌代码隐藏,您可以更花哨一点并创建诸如

public class GridSquareSizeBehavior : Behavior<Grid> {
  private UserControl _parent;

  protected override void OnAttached() {
    DependencyObject ucParent = AssociatedObject.Parent;
    while (!(ucParent is UserControl)) {
      ucParent = LogicalTreeHelper.GetParent(ucParent);
    }
    _parent = ucParent as UserControl;
    _parent.SizeChanged += SizeChangedHandler;
    base.OnAttached();
  }

  protected override void OnDetaching() {
    _parent.SizeChanged -= SizeChangedHandler;
    base.OnDetaching();
  }

  private void SizeChangedHandler(object sender, SizeChangedEventArgs e) {
    double minNewSizeOfParentUserControl = Math.Min(e.NewSize.Height, e.NewSize.Width);
    AssociatedObject.Width = minNewSizeOfParentUserControl;
    AssociatedObject.Height = minNewSizeOfParentUserControl;
  }
}

对于您的 xaml 的行为,如下所示:

  <Grid>
    <i:Interaction.Behaviors>
      <local:GridSquareSizeBehavior />
    </i:Interaction.Behaviors>
  </Grid>

是否使用 Snoop 测试了这两种方法,并且在扩展/收缩时保持了正方形大小。请注意,关键中的两种方法都使用相同的逻辑(只是一个快速模型),如果您将逻辑更新为仅在宽度更改时更新高度,反之亦然,而不是同时更新并取消,您可能能够获得更好的性能如果不需要,可以一起调整大小

关于wpf - 创建一个方形用户控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15603096/

相关文章:

c# - 什么决定了 NavigationCommands.BrowseBack 是否调用页面构造函数?

WPF 损坏状态异常。如何实现 HandleProcessCorruptedStateExceptions

wpf - 设置单个 WPF 用户控件的文化

wpf - DataGrid 通过单击 UpdateSourceTrigger = SourceUpdated 捕获单元格值更改事件

c# - 仅当设置了属性时才应用样式

javascript - 如何将事件从 VB.Net 类库/用户控件 (ActiveX) 提升到 JavaScript?

c# - Ninject.Web 和用户控件

wpf - Grid 的 SharedSizeGroup 和 * 大小调整

java - 表示可以放大和缩小的 2D map /网格的良好数据结构?

wpf - RowDefinition 高度 ="10*"在 XAML 网格中意味着什么?