c# - 如何在 C# 中绑定(bind)到 Grid ColumnDefinition Width

标签 c# xamarin xamarin.forms

我有一个绑定(bind):

public static readonly BindableProperty 
   EntryWidthProperty = BindableProperty.Create(nameof(EntryWidth),
   typeof(int),
   typeof(SingleEntryGrid), 150, BindingMode.TwoWay);
public int EntryWidth { 
   get => (int)GetValue(EntryWidthProperty); 
   set => SetValue(EntryWidthProperty, value); 
}
和这个 C# 代码:
var column3 = new ColumnDefinition()
{
   Width = new GridLength(???, GridUnitType.Absolute)
};
请注意, GridLength 是一个结构:
https://docs.microsoft.com/en-us/dotnet/api/xamarin.forms.gridlength?view=xamarin-forms
enter image description here
有谁知道我如何绑定(bind)到标有???
有关更多解释,这是我正在尝试做的:
enter image description here
我希望能够设置输入框框架的宽度。在这个例子中,它们的宽度都相同。

最佳答案

你不能那样做。正如您所说, GridLength 是一个结构,但可能比这更重要的是,您设置的 Value 只是一个带有 getter 的公共(public)属性(它甚至不是 BindableProperty )。这意味着你只能通过一个方法来设置它,在这种情况下它恰好是 GridLength ctor 本身。您可以检查 GridLength here 的代码。
你可以做的是两件事之一 - 要么保留所有你需要的宽度为 Auto ,要么继承 Grid 类。
如果您决定采用第一种方法,则不必编写任何额外的代码。根据 Rows and columns 文档:

Auto – the row height or column width is autosized based on the cell contents (Auto in XAML).


乍一看,这应该可以解决问题,因为所有宽度都将采用子项宽度的最大值(在本例中为 150)。不幸的是,这给 Grid 的渲染增加了一些开销,而且在任何情况下都不小。如果你稍微往下看文档,你会看到一个红色警告,你应该:

Try to ensure that as few rows and columns as possible are set to Auto size. Each auto-sized row or column will cause the layout engine to perform additional layout calculations. Instead, use fixed size rows and columns if possible. Alternatively, set rows and columns to occupy a proportional amount of space with the GridUnitType.Star enumeration value.


这也可以在 Optimize layout performance 中再次看到,如果您还没有阅读,我强烈建议您阅读。
话虽如此,您可以采用第二种方法。它背后的想法是在你的新类中有一个可绑定(bind)的属性,在设置这个属性时,你将更新 ColumnDefinitionWidth 属性。不幸的是,这必须“手动”完成。这是您的属性的示例(我已将其类型更改为 double 以与列的 Width 属性相同):
public partial class MainPage
{
    private ColumnDefinition column3;
    
    public static readonly BindableProperty EntryWidthProperty = BindableProperty.Create(nameof(EntryWidth), typeof(double),
        typeof(SingleEntryGrid), (double) 150, BindingMode.TwoWay);
    public double EntryWidth
    {
        get => (double) GetValue(EntryWidthProperty);
        set
        {
            SetValue(EntryWidthProperty, value);
            if (column3 != null)
            {
                column3.Width = value;
            }
        }
    }
    public MainPage()
    {
        InitializeComponent();
    
        var grid = new SingleEntryGrid
        {
            ColumnDefinitions = new ColumnDefinitionCollection()
        };
        // TODO: Other columns
        column3 = new ColumnDefinition
        {
            // The default value for EntryWidth
            Width = new GridLength(150, GridUnitType.Absolute)
        };
        grid.ColumnDefinitions.Add(column3);
        // The rest of your code
        
        Content = grid;
    }
}
正如您在代码中看到的,第三列最初设置为 Absolute 宽度 150(EntryWidth 的默认值)。在 EntryWidth 属性的值发生一些变化后,setter 将自动更改第三列。
当然,这不是最优雅的解决方案,因为它总是只更新第三列,但您可以从这里继续。由于我不知道究竟是什么情况以及它将用于什么,我不能说什么是最佳选择 - 为每列创建更多属性,或者使用键值创建它们的列表(甚至可能是一个单独的类)绑定(bind)到它们 - 这样你就可以为每一列动态设置它。
附言而且,如果您从一开始就知道您的宽度,或者您只有 1 列需要 Auto ,请使用传统方法。尽量不要使一切过于复杂,并相应地设置您的列定义。
编辑:根据更新的问题,我们应该采取另一种方法。从图像中我无法完全理解整体模板是什么,但我们在这里有 2 个选项:
  • 使所有输入在任何地方都具有相同的宽度;
  • 或者有不同的宽度。

  • 但是,无论我们选择什么,所有 View 的列都将具有相同的宽度。在这种情况下,我可以建议所有输入的宽度也相同(将它们的 HorizontalOptions 设置为 StartAndExpandFillAndExpand )。而不是明确设置它们的宽度,您可以尝试将列的宽度设置为(取决于您其他列的配置):
  • 如果您没有将其他列设置为 Star (*) 或者您不希望该列与其他星星成比例 - 将其宽度设置为 Star 。这样,该列将采用剩余的任何内容。
  • 或将列的宽度设置为 Absolute 值。

  • 您不应该尝试动态更改列 - 这不会是一个好的 UX,您还必须添加检查何时停止。
    总而言之,将第三列(包含条目)设置为 StarAbsolute 。如果您的其他一列设置为 Auto 并且另一列具有 Absolute 宽度,则您可以轻松地将第三列设置为 Star ,这将占用与剩余宽度一样多的宽度)。如果您想每次都采用“那么多”的宽度(将其与您希望可见的最大条目/符号一起使用),则应使用 Absolute

    关于c# - 如何在 C# 中绑定(bind)到 Grid ColumnDefinition Width,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62473192/

    相关文章:

    azure - 在 Xaramin 和 Azure 通知中心注册用户标签

    android - 如何访问适用于 iOS 和 Android 的 Xamarin.Forms 中的目录路径?

    xamarin.forms - 如何使用刷新 token 通过 Xamarin.Forms 客户端从身份服务器 4 获取新的访问 token

    xamarin.forms - NETSTANDARD 错误 一个或多个项目目标不支持构建操作 'EmbeddedResource'

    c# - Xamarin表单-C#-异步和等待不起作用?

    c# - 最接近数字的linq sql

    c# - SignalR Client 是否在 .NET Compact Framework 上运行?

    android - Xamarin 初学者 + 独立 VS 2015

    azure - 带有 Azure 通知中心的 Xamarin Forms IOS

    c# - <BitmapImage>.SetSource() 中的 OutOfMemory 异常