[英]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 條件不起作用。
顯示所有標簽。
而斷點,設置為NullToFalseBoolConverter
的Convert
方法的第一行沒有到達。
我不明白為什么會這樣。
有任何想法嗎?
這很有趣,但以下方法解決了我的問題。
我已經將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;
}
編輯
因此,作為將所選項目傳遞給您的命令方面您想要做的事情的補充,您可以執行以下操作。 我假設您的整個頁面是一個 ,但相同的概念確實適用於任何類型的頁面。
在 上設置一個x:Name
屬性,給它任何你想要的名字。 前任:
<ContentPage ... x:Name="root">
在標簽上定義<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>
在綁定到頁面的視圖模型中,創建以下命令,如下所示:
public ICommand YourCommandName => new Command(x => YourCustomMethodHere(x));
最后創建處理您選擇的對象的方法
public void YourCustomMethodHere(MyCustomType type) {}
那么上面的XAML代碼所做的就是我們將Label的命令綁定到整個父視圖模型,當一個項目在它的ItemSource定義的DataTemplate內部時,它的視圖模型實際上是正在被定義的模型使用了數據模板; 這就是我們將其源 VM 設置為整個父級的原因。 CommandParameter="{Binding .}"
與之前的邏輯相同,我們正在綁定整個數據模板項,在本例中是為該元素呈現的MyCustomType
。 這樣,每次點擊該標簽時,我們都會將該標簽及其數據傳遞給我們現在在 VM 中定義的命令。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.