c# - 有没有办法通过 x :Name as an alternative to its zero-based index? 引用网格列

标签 c# wpf grid

在我的代码中,我可以使用它的索引来引用列。但我更愿意使用它的名字。这可能吗?我不知道。 :D

<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="800">   

<Grid ShowGridLines="True">
    <Grid.ColumnDefinitions>
        <ColumnDefinition x:Name="LeftColumn" Width="200"></ColumnDefinition>
        <ColumnDefinition x:Name="MiddleColumn" Width="200"></ColumnDefinition>
        <ColumnDefinition x:Name="RightColumn" Width="*"></ColumnDefinition>
    </Grid.ColumnDefinitions>

    <Button x:Name="WelcomeButton" Grid.Column="1">Click me.</Button> //Here!
</Grid>

编辑:

如果无法通过名称引用它,那么为列设置名称有什么用? (我是 WPF 的新手:P)

最佳答案

是的! WPF 的美妙之处在于添加您想要的功能是多么的简单。您可以使用附加属性轻松添加命名的网格行和列。例如,下面的代码将允许您执行此操作:

<Grid ShowGridLines="True">
  <Grid.ColumnDefinitions>
    <ColumnDefinition x:Name="LeftColumn" Width="200" />
    <ColumnDefinition x:Name="MiddleColumn" Width="200" />
    <ColumnDefinition x:Name="RightColumn" Width="*" />
  </Grid.ColumnDefinitions>
  <Button my:Grid_Named.Column="RightColumn">Click me.</Button>
</Grid>

这是代码本身。非常简单,只花了几分钟就写完了:

public static class Grid_Named
{
  // Define Grid_Name.Column property
  public static string GetColumn(DependencyObject obj) { return (string)obj.GetValue(ColumnProperty); }
  public static void SetColumn(DependencyObject obj, string value) { obj.SetValue(ColumnProperty, value); }
  public static readonly DependencyProperty ColumnProperty = DependencyProperty.RegisterAttached("Column", typeof(string), typeof(Grid_Named), new UIPropertyMetadata
  {
    PropertyChangedCallback = (obj, e) =>
      {
        if(e.OldValue!=null) BindingOperations.ClearBinding(obj, Grid.ColumnProperty);
        if(e.NewValue!=null) BindingOperations.SetBinding(obj, Grid.ColumnProperty, _columnBinding);
      },
  });

  // Define Grid_Named.Row property
  public static string GetRow(DependencyObject obj) { return (string)obj.GetValue(RowProperty); }
  public static void SetRow(DependencyObject obj, string value) { obj.SetValue(RowProperty, value); }
  public static readonly DependencyProperty RowProperty = DependencyProperty.RegisterAttached("Row", typeof(string), typeof(Grid_Named), new UIPropertyMetadata
  {
    PropertyChangedCallback = (obj, e) =>
    {
      if(e.OldValue!=null) BindingOperations.ClearBinding(obj, Grid.RowProperty);
      if(e.NewValue!=null) BindingOperations.SetBinding(obj, Grid.RowProperty, _rowBinding);
    },
  });

  // Construct bindings for Grid.Column and Grid.Row
  private static BindingBase _columnBinding = BuildBinding(grid => grid.ColumnDefinitions, ColumnProperty);
  private static BindingBase _rowBinding = BuildBinding(grid => grid.RowDefinitions, RowProperty);
  private static BindingBase BuildBinding(Func<Grid, IList> getDefinitions, DependencyProperty nameProperty)
  {
    var binding = new MultiBinding
    {
      Converter = new NameLookupConverter { GetDefinitions = getDefinitions }
    };
    binding.Bindings.Add(new Binding { Path = new PropertyPath(nameProperty), RelativeSource = RelativeSource.Self });
    binding.Bindings.Add(new Binding { RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(Grid), 1) });
    return binding;
  }

  // Converter to take a row/column name and a Grid, and find the index of that row/column in the grid
  private class NameLookupConverter : IMultiValueConverter
  {
    public Func<Grid, IList> GetDefinitions;

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
      var name = values[0] as string;
      var grid = values[1] as Grid;

      if(grid==null || name==null) return 0;

      object namedObject = grid.FindName(name);
      if(namedObject==null) return 0;

      int index = GetDefinitions(grid).IndexOf(namedObject);
      return index<0 ? 0 : index;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
      throw new NotImplementedException();
    }
  }
}

如您所见,无论何时添加附加属性 Grid_Named.Column 或 Grid_Named.Row,它都只是为 Grid.Column 或 Grid.Row 创建一个绑定(bind),使用 IMultiValueConveter 选择适当的列号或行号。

很简单,不是吗?

关于c# - 有没有办法通过 x :Name as an alternative to its zero-based index? 引用网格列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1719167/

相关文章:

c# - 更新现有目录 - Apache-POI |开发工具包 |其他接口(interface)

c# - WPF 自定义控件 : Bind CollectionViewSource to DependencyProperty

c# - 如何播放正在编码的视频?

HTML CSS : How to align grid to content area?

ExtJS 4 - 在网格面板中包装列标题

c# - 使直线而不是矩形无效

c# - 将 JSON 解析为 C# 对象 - 动态获取属性

c# - WPF C# LINQ : Operator '&&' cannot be applied to operands of type 'string' and 'string' query

c# - Windows Phone 8 用户在网格中拖放网格

c# - 声明一个常量数组