C# 如何使用带有null参数的x:Bind函数绑定?

C# 如何使用带有null参数的x:Bind函数绑定?,c#,xaml,data-binding,uwp,xbind,C#,Xaml,Data Binding,Uwp,Xbind,我试图格式化一个对象的几个属性,并使用x:bind函数绑定将结果绑定到TextBlock。绑定如下所示: <TextBlock Text="{x:Bind local:MainViewModel.FormatWidget(ViewModel.SelectedItem), Mode=OneWay}" /> MainPage.xaml.cs using Windows.UI.Xaml.Controls; namespace NullFunctionBindingParameter {

我试图格式化一个对象的几个属性,并使用
x:bind
函数绑定将结果绑定到
TextBlock
。绑定如下所示:

<TextBlock Text="{x:Bind local:MainViewModel.FormatWidget(ViewModel.SelectedItem), Mode=OneWay}" />
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();
    }
}
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);
        }
    }
}
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)));
                }
            }
        }
    }
}
MainViewModel.cs

using Windows.UI.Xaml.Controls;

namespace NullFunctionBindingParameter
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            InitializeComponent();
        }

        public MainViewModel ViewModel { get; } = new MainViewModel();
    }
}
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);
        }
    }
}
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)));
                }
            }
        }
    }
}

在这种情况下,我建议您使用
Converter
,而不是直接在binding语句中使用静态方法

WidgetConverter

公共类WidgetConverter:IValueConverter
{
公共对象转换(对象值、类型targetType、对象参数、字符串语言)
{
var widget=作为widget的值;
返回MainViewModel.FormatWidget(小部件);
}
公共对象转换回(对象值、类型targetType、对象参数、字符串语言)
{
抛出新的NotImplementedException();
}
}
用法


...
...

致意。

谢谢你的建议。当然,这将是获得相同产出的有效途径;然而,我真的很喜欢的简易性和可读性,并希望有一个解决方案,不需要回到转换器。目前没有好的解决方案。函数绑定中可能有一种拦截机制,防止在计算中使用null。转换器没有这种问题,建议使用method@RichardZhangMSFT根据,鼓励使用函数格式化和转换值:“提示您可以使用x:Bind中的函数来实现与WPF中的转换器和多绑定支持的场景相同的场景。”并说,“{x:Bind}”使绑定路径中的最后一步成为函数。这可用于执行转换,以及执行依赖于多个属性的绑定。“您好,这可能是对绑定设计的疏忽
Converter
可以用作解决问题的临时解决方案。这是作为GitHub上的一个组件添加的。