簡體   English   中英

如何綁定到 C# 中的 Grid ColumnDefinition Width

[英]How can I bind to a Grid ColumnDefinition Width in C#

我有一個綁定:

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://learn.microsoft.com/en-us/do.net/api/xamarin.forms.gridlength?view=xamarin.forms

在此處輸入圖像描述

有誰知道我如何綁定到標有的值???

有關更多解釋,這是我正在嘗試做的事情:

在此處輸入圖像描述

我希望能夠設置輸入框框架的寬度。 在此示例中,它們的寬度都相同。

你不能那樣做。 正如您所說, GridLength是一個結構,但可能比這更重要的是您設置的Value只是一個帶有 getter 的公共屬性(它甚至不是BindableProperty )。 這意味着您只能通過一種方法來設置它,在本例中恰好是GridLength構造函數本身。 您可以在此處查看 GridLength 的代碼。

您可以做的是兩件事之一 - 保留您需要的所有寬度Auto ,或者將Grid class 子類化。

如果您決定使用第一種方法 go,則無需編寫任何額外的代碼。 根據行和列文檔:

Auto – 行高或列寬根據單元格內容自動調整(XAML 中的 Auto)。

乍一看,這應該可以完成工作,因為所有寬度都將采用子寬度的最大值(在本例中為 150)。 不幸的是,這給Grid的渲染增加了一些開銷,而且在任何情況下都不小。 如果你在文檔中看得有點低,你會看到一個紅色警告,你應該:

盡量確保將盡可能少的行和列設置為Auto大小。 每個自動調整大小的行或列都會導致布局引擎執行額外的布局計算。 相反,如果可能,請使用固定大小的行和列。 或者,使用 GridUnitType.Star 枚舉值設置行和列以占用一定比例的空間。

這也可以在優化布局性能中再次看到,如果您還沒有閱讀,我強烈建議您閱讀。

也就是說,您可以使用第二種方法 go。 它背后的想法是在你的新 class 中有一個可綁定的屬性,並且在設置這個屬性時,你將更新你的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 將自動更改第三列。

當然,這不是最優雅的解決方案,因為它總是只更新第三列,但您可以從這里繼續。 由於我不確切知道情況是什么以及它會被用來做什么,我不能說什么是最好的選擇 - 要么為每一列創建更多屬性,要么創建一個包含鍵值的列表(甚至可能是一個單獨的類)綁定到它們 - 這樣你就可以為每一列動態設置它。

PS 而且,如果您從一開始就知道寬度,或者您只有 1 列需要Auto ,則 go 使用傳統方法。 盡量不要讓一切都過於復雜,並相應地設置列定義。

編輯:根據更新的問題,我們應該采取另一種方法。 從圖像中我無法完全理解整體模板是什么,但我們在這里有 2 個選項:

  1. 讓所有輸入在任何地方都具有相同的寬度;
  2. 或者有不同的寬度。

然而,無論我們選擇什么,該列對於所有視圖都將具有相同的寬度。 在這種情況下,我可以建議的是讓所有輸入的寬度也相同(將它們的HorizontalOptions ntalOptions 設置為StartAndExpandFillAndExpand )。 而不是明確設置它們的寬度,您可以嘗試將列的寬度設置為(取決於其他列的配置):

  1. 如果您沒有將其他列設置為Star (*) 或者您不希望該列與其他星號成比例 - 將其寬度設置為Star 這樣,該列將占用剩余的所有內容。
  2. 或者將列的寬度設置為Absolute

您不應該嘗試動態更改列 - 這不會是一個好的用戶體驗,您還必須添加檢查何時停止。

總而言之,要么將第三列(包含條目)設置為Star ,要么設置為Absolute 如果您的其他列之一設置為Auto而另一列具有Absolute寬度,您可以輕松地將第三列設置為Star ,它將占用與剩余寬度相同的寬度)。 如果您想每次都使用“那么多”的寬度,則應使用Absolute (將其與您希望可見的最大條目/符號一起使用)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM