オブジェクトのいくつかのプロパティをフォーマットし、その結果をTextBlockusingx:Bind関数バインディングにバインドしようとしています。バインディングは次のようになります。
<TextBlock Text="{x:Bind local:MainViewModel.FormatWidget(ViewModel.SelectedItem), Mode=OneWay}" />
オブジェクトがnullでない限り、これは完全に機能します。ただし、オブジェクトがnullの場合、関数は呼び出されません。より正確には、オブジェクトが最初にnullの場合、関数が呼び出されますが、後でオブジェクトがnullに変更された場合、関数は呼び出されません。
パラメータがnullの場合に関数が呼び出されないのはなぜですか?この場合、どのように使用できますか?
これが再現です。実行すると、最初は関数がnull SelectedItemに正しくバインドされ、 「ウィジェットが選択されていません」と表示されることに注意してください。ただし、項目を選択してから選択を解除すると ( CTRL + クリックして選択を解除)、関数は呼び出されず、FallbackValue. (FallbackValueが設定されていない場合、バインディングはまったく更新されません。)
MainPage.xaml
<Page
x:Class="NullFunctionBindingParameter.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:NullFunctionBindingParameter">
<Page.Resources>
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="20" />
</Style>
</Page.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListView
Grid.Column="0"
ItemsSource="{x:Bind ViewModel.Widgets, Mode=OneWay}"
SelectedItem="{x:Bind ViewModel.SelectedItem, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Widget">
<TextBlock Text="{x:Bind Name}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<TextBlock Grid.Column="1" Text="{x:Bind local:MainViewModel.FormatWidget(ViewModel.SelectedItem), Mode=OneWay, FallbackValue=MyFallbackValue}" />
</Grid>
</Page>
MainPage.xaml.cs
using Windows.UI.Xaml.Controls;
namespace NullFunctionBindingParameter
{
public sealed partial class MainPage : Page
{
public MainPage()
{
InitializeComponent();
}
public MainViewModel ViewModel { get; } = new MainViewModel();
}
}
MainViewModel.cs
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace NullFunctionBindingParameter
{
public class MainViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private Widget _selectedItem;
public Widget SelectedItem
{
get => _selectedItem;
set
{
if (_selectedItem != value)
{
_selectedItem = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedItem)));
}
}
}
public ObservableCollection<Widget> Widgets { get; } = new ObservableCollection<Widget>()
{
new Widget
{
Id = Guid.NewGuid(),
Name = "Regular Widget",
Model = "WX2020-01",
Description = "Your typical everyday widget."
},
new Widget
{
Id = Guid.NewGuid(),
Name = "Super Widget",
Model = "WX2020-02",
Description = "An extra special upgraded widget."
},
new Widget
{
Id = Guid.NewGuid(),
Name = "Broken Widget",
Model = "WX2020-03",
Description = "A widget that has been used and abused."
},
new Widget
{
Id = Guid.NewGuid(),
Name = "Fake Widget",
Model = "WX2020-04",
Description = "It's not really a widget at all!"
},
new Widget
{
Id = Guid.NewGuid(),
Name = "Surprise Widget",
Model = "WX2020-05",
Description = "What kind of widget will it be?"
},
new Widget
{
Id = Guid.NewGuid(),
Name = "Invisible Widget",
Model = "WX2020-06",
Description = "Our most inexpensive widget."
},
new Widget
{
Id = Guid.NewGuid(),
Name = "Backwards Widget",
Model = "WX2020-07",
Description = "Really more of a tegdiw, come to think of it."
}
};
public static string FormatWidget(Widget widget)
{
if (widget == null)
return "No widget selected";
else
return $"{widget.Name} [{widget.Model}] {widget.Description}";
}
public string GetFormattedWidget()
{
return FormatWidget(SelectedItem);
}
}
}
Widget.cs
using System;
using System.ComponentModel;
namespace NullFunctionBindingParameter
{
public class Widget : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private Guid _id;
private string _name;
private string _model;
private string _description;
public Guid Id
{
get => _id;
set
{
if (_id != value)
{
_id = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Id)));
}
}
}
public string Name
{
get => _name;
set
{
if (_name != value)
{
_name = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
}
}
}
public string Model
{
get => _model;
set
{
if (_model != value)
{
_model = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Model)));
}
}
}
public string Description
{
get => _description;
set
{
if (_description != value)
{
_description = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Description)));
}
}
}
}
}