我正在為我在整個應用程式中使用的常見容器型別制作自定義 ContentView。自定義視圖有兩個可系結屬性:要在左上角顯示的標題(字串),以及要在右上角顯示的按鈕串列(List)。
header 屬性(和 Contents 屬性)按預期作業,但 button 屬性根本不起作用。永遠不會觸發,并且輸出控制臺中ButtonsPropertyChanged沒有系結錯誤訊息。我究竟做錯了什么?
主頁.xaml:
<controls:SectionContainer Header="Text blah"> <!-- Header works -->
<controls:SectionContainer.Buttons>
<!-- This does NOT work - buttons are not shown -->
<ImageButton Source="{Binding SomeIcon}"></ImageButton>
<ImageButton Source="{Binding AnotherIcon}"></ImageButton>
</controls:SectionContainer.Buttons>
<!-- Actual contents here -- this works, the contents are shown -->
</controls:SectionContainer>
SectionContainer.xaml:
<ContentView.Content>
<Frame Style="{StaticResource SectionFrame}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Label x:Name="HeaderLabel" Grid.Column="0" Grid.Row="0" VerticalTextAlignment="Start" VerticalOptions="Start" Style="{StaticResource Header}"></Label>
<StackLayout x:Name="ButtonsContainer" Grid.Row="0" Grid.Column="1" Orientation="Horizontal" HorizontalOptions="End"></StackLayout>
<StackLayout Grid.Column="0" Grid.Row="1" x:Name="Container" Style="{StaticResource Section}"></StackLayout>
</Grid>
</Frame>
</ContentView.Content>
SectionContainer.xaml.cs:
[XamlCompilation(XamlCompilationOptions.Compile)]
[ContentProperty("Contents")]
public partial class SectionContainer : ContentView
{
public IList<View> Contents => Container.Children;
public string Header
{
get => (string)GetValue(HeaderProperty);
set => SetValue(HeaderProperty, value);
}
public static readonly BindableProperty HeaderProperty = BindableProperty.Create(
nameof(Header),
typeof(string),
typeof(SectionContainer),
"",
propertyChanged: HeaderPropertyChanged);
private static void HeaderPropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
{
((SectionContainer) bindable).HeaderLabel.Text = (string) newvalue;
}
public IList<View> Buttons
{
get => (IList<View>)GetValue(ButtonsProperty);
set => SetValue(ButtonsProperty, value);
}
public static readonly BindableProperty ButtonsProperty = BindableProperty.Create(
nameof(Buttons),
typeof(IList<View>),
typeof(SectionContainer),
new List<View>(),
BindingMode.OneWay,
propertyChanged: ButtonsPropertyChanged);
private static void ButtonsPropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
{
Debug.WriteLine(newvalue); // This is never printed, and there are no error messages
var children= ((SectionContainer)bindable).ButtonsContainer.Children;
children.Clear();
foreach (var child in (IList<View>) newvalue)
children.Add(child);
}
public SectionContainer()
{
InitializeComponent();
}
}
uj5u.com熱心網友回復:
Xamarin.Forms 不設定屬性,它將元素添加到作為默認值創建的物件。
因此,ObservableCollection創建 using defaultValueCreator(而不是defaultValue),我們在其中偵聽更改并填充用戶控制元件似乎可以作業。不確定我們是否需要該propertyChanged事件,或者我們是否需要處理ObservableCollection除單個元素添加之外的任何其他事件,但我保留它以防萬一。
public static readonly BindableProperty ButtonsProperty = BindableProperty.Create(
nameof(Buttons),
typeof(IList<View>),
typeof(SectionContainer),
propertyChanged: ButtonsPropertyChanged,
defaultValueCreator: CreateObservableList);
private static object CreateObservableList(BindableObject bindable)
{
var oc = new ObservableCollection<View>();
// It appears Xamarin.Forms doesn't create a list containing the Views from the XAML, it uses the default value (list),
// and adds the Views one by one. Therefore, we create the default value as an ObservableCollection, then we listen
// for changes to this collection.
oc.CollectionChanged = (o, e) =>
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
// If this is an Add operation, simply add the view to the StackLayout.
var children = ((SectionContainer) bindable).ButtonsContainer.Children;
foreach (var child in e.NewItems.Cast<View>())
children.Add(child);
}
else
{
// Otherwise, recreate the StackLayout by clearing it, and adding all children all over again.
// (Won't bother handling all cases, since the normal one seems to be Add anyway.)
ButtonsPropertyChanged(bindable, null, o);
}
};
return oc;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/437767.html
標籤:xamarin xamarin.forms 可绑定属性
上一篇:如何在xamarin中集成googlepay以用于iOS應用程式?
下一篇:如何從泛型方法訪問類的方法
