簡體   English   中英

Xamarin.Forms。 XAML Label IsVisible 條件未按預期進行評估

[英]Xamarin.Forms. XAML Label IsVisible condition is not getting evaluated as expected

在我的項目中,我必須在頁面上選擇多個選項。

每個選項都有一個MyCustomType類型並聲明了公共字符串Name屬性。

每個選項都通過標簽顯示。 當我點擊標簽時,我會顯示選項列表並選擇它。

選擇一個選項后,帶有占位符文本(例如select an item )的另一個選項的空標簽應出現在帶有剛剛選擇的選項的標簽下方。

我為每個選項使用單獨的標簽,而不是 ListView 元素(客戶對特定外觀的要求)。

選項的數量是有限的,假設它等於四個。

在我的視圖模型中,我已經聲明了列表屬性(它已在視圖模型構造函數中初始化):

public List<MyCustomType> AllOptions { get; }

在我的 XAML 頁面標簽中聲明為:

<Label Text="{Binding AllOptions[0].Name}" >

<Label Text="{Binding AllOptions[1].Name}" IsVisible="{Binding AllOptions[0], Converter={StaticResource NullToFalseBoolConverter}}">

<Label Text="{Binding AllOptions[2].Name}" IsVisible="{Binding AllOptions[1], Converter={StaticResource NullToFalseBoolConverter}}">

<Label Text="{Binding AllOptions[3].Name}" IsVisible="{Binding AllOptions[2], Converter={StaticResource NullToFalseBoolConverter}}">

轉換器NullToFalseBoolConverter看起來像這樣:

public class NullToFalseBoolConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value != null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

問題是在標簽聲明中指定的 IsVisible 條件不起作用。

顯示所有標簽。

而斷點,設置為NullToFalseBoolConverterConvert方法的第一行沒有到達。

我不明白為什么會這樣。

有任何想法嗎?

這很有趣,但以下方法解決了我的問題。

我已經將AllOptions聲明為List (不起作用)和ObservableCollection (也不起作用)。

我應該將我的列表聲明為數組

public MyCustomType[] AllOptions { get; }

我的標簽開始正常顯示,一個接一個設置。

在處理它的值時,如果我得到空值,這意味着我們到達了填充選項的末尾。

與其嘗試綁定,不如考慮使用既支持 ItemSource 又支持數據模板的布局類型。 所以這類似於 ListView/CollectionView/Stacklayout

因此,例如,如果您決定使用 StackLayout,例如:

<StackLayout
...
BindableLayout.ItemsSource="{Binding AllOptions}">
<BindableLayout.ItemTemplate>
        <DataTemplate>
            <Label Text="{Binding Name}" IsVisible="{Binding ., Converter={StaticResource NullToFalseBoolConverter}}">

        </DataTemplate>
    </BindableLayout.ItemTemplate>
</StackLayout>

這種方法的美妙之處在於,由於您的標簽都遵循相同的方法,您現在不僅可以 A) 編寫更簡潔的代碼,並且 B) 利用 MVVM 模式。 現在,當然這意味着每個控件也將轉換器應用於它們; 但是,如果仍然不想將它包含在第一個元素中,那么我們要做的就是更改您的類型以包含索引屬性。 如果您想知道Binding .的語法是什么Binding . 意味着,這意味着我們只是為該元素綁定了該集合的整個對象。

public int Index {get; set;}

將它設置在您構建該數組的位置,然后在轉換器中您所要做的就是:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var element = (MyCustomType) value;
if(element.Index != 0)
        return value != null;
else
        return true;
}

編輯

因此,作為將所選項目傳遞給您的命令方面您想要做的事情的補充,您可以執行以下操作。 我假設您的整個頁面是一個 ,但相同的概念確實適用於任何類型的頁面。

  1. 在 上設置一個x:Name屬性,給它任何你想要的名字。 前任:

    <ContentPage ... x:Name="root">

  2. 在標簽上定義<GestureRecognizer>

<Label Text="{Binding Name}" IsVisible="{Binding ., Converter={StaticResource NullToFalseBoolConverter}}"> <Label.GestureRecognizers> <TapGestureRecognizer Command="{Binding BindingContext.YourCommandName, Source={x:Reference root}}" CommandParameter="{Binding .}"/> </Label.GestureRecognizers>

  1. 在綁定到頁面的視圖模型中,創建以下命令,如下所示:

    public ICommand YourCommandName => new Command(x => YourCustomMethodHere(x));

  2. 最后創建處理您選擇的對象的方法

    public void YourCustomMethodHere(MyCustomType type) {}

那么上面的XAML代碼所做的就是我們將Label的命令綁定到整個父視圖模型,當一個項目在它的ItemSource定義的DataTemplate內部時,它的視圖模型實際上是正在被定義的模型使用了數據模板; 這就是我們將其源 VM 設置為整個父級的原因。 CommandParameter="{Binding .}"與之前的邏輯相同,我們正在綁定整個數據模板項,在本例中是為該元素呈現的MyCustomType 這樣,每次點擊該標簽時,我們都會將該標簽及其數據傳遞給我們現在在 VM 中定義的命令。

暫無
暫無

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

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