转换器中的 WPF MultiBinding 失败 ==> DependencyProperty.UnsetValue

发布于 2024-11-26 02:55:33 字数 6309 浏览 0 评论 0原文

我的代码在启动时失败,因为由 Multibound 调用的 Converter 中的值数组未填充正确的值,但值为 DependencyProperty.UnsetValue

看看转换器,也看看我在哪里遇到错误

public class ButtonColorConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            string val1 = string.Format("  {0}  ", values[0]);
            string val2 = (string)values[1];  **//Here i am getting ==> {DependencyProperty.UnsetValue}** 
            return val1.Equals(val2)
                ? Brushes.NavajoWhite
                : Brushes.White;  
        }

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

你可以下载

MainWindow.xaml

<Window x:Class="DataPager.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        xmlns:Local="clr-namespace:DataPager.Convertor_For_BackGround">
    <Grid>
        <Grid.Resources>
            <Local:ButtonColorConverter x:Key="currentPageSetter"/>
        </Grid.Resources>
        <Grid.RowDefinitions>
            <RowDefinition Height="36*" />
            <RowDefinition Height="275*" />
        </Grid.RowDefinitions>
        <ItemsControl Name="pageControl" ItemsSource="{Binding Path=PageCollection}" Grid.Row="0">
            <ItemsControl.Template>
                <ControlTemplate TargetType="ItemsControl">
                    <Border >
                        <StackPanel>
                            <ItemsPresenter></ItemsPresenter>
                        </StackPanel>
                    </Border>
                </ControlTemplate>
            </ItemsControl.Template>
            <ItemsControl.ItemsPanel x:Uid="pageItemTemplate">
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button x:Name="pageNumberButton" Margin="3,4" Content="{Binding Path=Page_Number}">
                        <Button.Background>
                            <MultiBinding Converter="{StaticResource currentPageSetter}">
                                <Binding Path="Page_Number" />
                                <Binding Path="CurrentPage.Page_Number" /> **//This Binding not resolves properly**
                            </MultiBinding>
                        </Button.Background>
                    </Button>
                </DataTemplate>
            </ItemsControl.ItemTemplate>

        </ItemsControl>
        <TextBox Text="{Binding Path=CurrentPage.Page_Number,Mode=TwoWay, FallbackValue=asdf}" Grid.Row="1" Height="23"  Margin="79,62,257,0" Name="textBox1" VerticalAlignment="Top" Width="167" />
    </Grid>
</Window>

MainWindow.xaml.cs

 public partial class MainWindow : Window
    {
        public MainWindow()
        {


            MyPageViewModel = new PageViewModel();

            MyPageViewModel.PageCollection.Add(new PageNumberViewModel(string.Format("  {0}  ",0)));
            MyPageViewModel.PageCollection.Add(new PageNumberViewModel(string.Format("  {0}  ",1)));
            MyPageViewModel.PageCollection.Add(new PageNumberViewModel(string.Format("  {0}  ",2)));
            MyPageViewModel.PageCollection.Add(new PageNumberViewModel(string.Format("  {0}  ",3)));

            InitializeComponent();
        }

        public PageViewModel MyPageViewModel
        {
            get
            {
                return this.DataContext as PageViewModel;
            }
            set
            {
                this.DataContext = value;
            }
        }
    }

这是 ViewModel 类。

PageViewModel.cs

public class PageViewModel:ViewModelBase
    {
        private ObservableCollection<PageNumberViewModel> m_pageCollection = new ObservableCollection<PageNumberViewModel>();
        private PageNumberViewModel m_currentPage = new PageNumberViewModel(string.Format("  {0}  ",0));

        public PageViewModel()
        {
            m_currentPage = new PageNumberViewModel(string.Format("  {0}  ", 1000));
        }

        public PageNumberViewModel CurrentPage 
        {
            get
            {
                return this.m_currentPage;
            }
            set
            {
                if (m_currentPage == value)
                    return;
                this.m_currentPage = value;
                base.OnPropertyChanged("CurrentPage");
            }
        }
        public ObservableCollection<PageNumberViewModel> PageCollection
        {
            get
            {
                return this.m_pageCollection;
            }
            set
            {
                if (m_pageCollection == value)
                    return;
                this.m_pageCollection = value;
                base.OnPropertyChanged("PageCollection");
            }
        }
    }

PageNumberViewModel。计算机科学

public class PageNumberViewModel : ViewModelBase
    {
        private string m_pageNumber;

        public PageNumberViewModel()              
        {

        }
        public PageNumberViewModel(string pageNumgerArg)
        {
            this.m_pageNumber = pageNumgerArg;
        }

        public string Page_Number
        {
            get { return m_pageNumber; }
            set
            {
                if (m_pageNumber == value)
                    return;
                m_pageNumber = value;
                OnPropertyChanged("PageNumber");
            }
        }

    }

My code fails at at startup because the values array in the Converter that is called by the Multibinding is not filled with proper value but have a value of DependencyProperty.UnsetValue.

have a look at Convertor and also see where i getting error

public class ButtonColorConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            string val1 = string.Format("  {0}  ", values[0]);
            string val2 = (string)values[1];  **//Here i am getting ==> {DependencyProperty.UnsetValue}** 
            return val1.Equals(val2)
                ? Brushes.NavajoWhite
                : Brushes.White;  
        }

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

You can download full code or see my codes snippet as per below.

MainWindow.xaml

<Window x:Class="DataPager.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        xmlns:Local="clr-namespace:DataPager.Convertor_For_BackGround">
    <Grid>
        <Grid.Resources>
            <Local:ButtonColorConverter x:Key="currentPageSetter"/>
        </Grid.Resources>
        <Grid.RowDefinitions>
            <RowDefinition Height="36*" />
            <RowDefinition Height="275*" />
        </Grid.RowDefinitions>
        <ItemsControl Name="pageControl" ItemsSource="{Binding Path=PageCollection}" Grid.Row="0">
            <ItemsControl.Template>
                <ControlTemplate TargetType="ItemsControl">
                    <Border >
                        <StackPanel>
                            <ItemsPresenter></ItemsPresenter>
                        </StackPanel>
                    </Border>
                </ControlTemplate>
            </ItemsControl.Template>
            <ItemsControl.ItemsPanel x:Uid="pageItemTemplate">
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button x:Name="pageNumberButton" Margin="3,4" Content="{Binding Path=Page_Number}">
                        <Button.Background>
                            <MultiBinding Converter="{StaticResource currentPageSetter}">
                                <Binding Path="Page_Number" />
                                <Binding Path="CurrentPage.Page_Number" /> **//This Binding not resolves properly**
                            </MultiBinding>
                        </Button.Background>
                    </Button>
                </DataTemplate>
            </ItemsControl.ItemTemplate>

        </ItemsControl>
        <TextBox Text="{Binding Path=CurrentPage.Page_Number,Mode=TwoWay, FallbackValue=asdf}" Grid.Row="1" Height="23"  Margin="79,62,257,0" Name="textBox1" VerticalAlignment="Top" Width="167" />
    </Grid>
</Window>

MainWindow.xaml.cs

 public partial class MainWindow : Window
    {
        public MainWindow()
        {


            MyPageViewModel = new PageViewModel();

            MyPageViewModel.PageCollection.Add(new PageNumberViewModel(string.Format("  {0}  ",0)));
            MyPageViewModel.PageCollection.Add(new PageNumberViewModel(string.Format("  {0}  ",1)));
            MyPageViewModel.PageCollection.Add(new PageNumberViewModel(string.Format("  {0}  ",2)));
            MyPageViewModel.PageCollection.Add(new PageNumberViewModel(string.Format("  {0}  ",3)));

            InitializeComponent();
        }

        public PageViewModel MyPageViewModel
        {
            get
            {
                return this.DataContext as PageViewModel;
            }
            set
            {
                this.DataContext = value;
            }
        }
    }

And this is ViewModel Classes.

PageViewModel.cs

public class PageViewModel:ViewModelBase
    {
        private ObservableCollection<PageNumberViewModel> m_pageCollection = new ObservableCollection<PageNumberViewModel>();
        private PageNumberViewModel m_currentPage = new PageNumberViewModel(string.Format("  {0}  ",0));

        public PageViewModel()
        {
            m_currentPage = new PageNumberViewModel(string.Format("  {0}  ", 1000));
        }

        public PageNumberViewModel CurrentPage 
        {
            get
            {
                return this.m_currentPage;
            }
            set
            {
                if (m_currentPage == value)
                    return;
                this.m_currentPage = value;
                base.OnPropertyChanged("CurrentPage");
            }
        }
        public ObservableCollection<PageNumberViewModel> PageCollection
        {
            get
            {
                return this.m_pageCollection;
            }
            set
            {
                if (m_pageCollection == value)
                    return;
                this.m_pageCollection = value;
                base.OnPropertyChanged("PageCollection");
            }
        }
    }

PageNumberViewModel.cs

public class PageNumberViewModel : ViewModelBase
    {
        private string m_pageNumber;

        public PageNumberViewModel()              
        {

        }
        public PageNumberViewModel(string pageNumgerArg)
        {
            this.m_pageNumber = pageNumgerArg;
        }

        public string Page_Number
        {
            get { return m_pageNumber; }
            set
            {
                if (m_pageNumber == value)
                    return;
                m_pageNumber = value;
                OnPropertyChanged("PageNumber");
            }
        }

    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

歌入人心 2024-12-03 02:55:33

当您在任何 ItemsSource 中设置列​​表时,各个项目的 DataTemplate 的 DataContext 将是列表中的每个项目。

确实,您的 TextBlock 绑定工作正常,因为 DataContext 设置为您的主对象: PageViewModel

但在您的 DataTemplate 中,DataContext 将设置为 PageNumberViewModel,因为这些是您收藏的物品。

因此,绑定到 Path=CurrentPage.Page_Number 将导致 UnsetValue,因为 CurrentPage 不是 PageNumberViewModel 的属性

希望这能澄清问题!

如果您确实希望绑定到窗口 DataContext 的 CurrentPage 属性,请考虑使用 ElementName 绑定:

为窗口指定名称,绑定到

<Binding ElementName="name" Path="DataContext.CurrentPage.Page_Number" />

或使用relativesource 绑定:

<Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}" Path="DataContext.CurrentPage.Page_Number" />

When you set a list in any ItemsSource, the DataTemplate's DataContext for the individual items will each item of the list.

True that your TextBlock binding is working correctly, because the DataContext is set to your main object: PageViewModel

But in your DataTemplate the DataContext will be set to PageNumberViewModel, since these are the items in your collection.

Therefor, the binding to Path=CurrentPage.Page_Number will result to UnsetValue, because CurrentPage is not a property of PageNumberViewModel

Hope this clarifies things!

If you truly wish to bind to the CurrentPage property of your Window's DataContext, consider using an ElementName binding:

Give window a name, bind to

<Binding ElementName="name" Path="DataContext.CurrentPage.Page_Number" />

or use a RelativeSource binding:

<Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}" Path="DataContext.CurrentPage.Page_Number" />
人生百味 2024-12-03 02:55:33

您似乎没有正确的 DataContext 来解析路径 CurrentPage.Page_Number。调试此类事情的一个好方法是删除路径,以便您可以检查值转换器中的 DataContext:

<Binding Path="." />

然后在 ButtonColorConverter 中设置一个断点,并准确查看您正在尝试的内容进行转换。

It looks like you might not have the correct DataContext to resolve the path CurrentPage.Page_Number. A good way of debugging this sort of thing is to remove the path so that you can inspect the DataContext within your value converter:

<Binding Path="." />

Then set a breakpoint in your ButtonColorConverter and have a look at exactly what you are trying to convert.

呆橘 2024-12-03 02:55:33

DependencyProperty.UnsetValue 只是 DependencyProperty 类的常量。

你可以这样做:

 if (values[1] == DependencyProperty.UnsetValue)
 {
     return null;  // or default value
 }

DependencyProperty.UnsetValue is merely a constant on the DependencyProperty class.

You can do something like this :

 if (values[1] == DependencyProperty.UnsetValue)
 {
     return null;  // or default value
 }
離人涙 2024-12-03 02:55:33

我也遇到了这个问题,并在另一篇文章中找到了解决方案(https://stackoverflow.com/a/3139397/500099 )。关键是使用 FallbackValue="" 属性,如下所示:

<MultiBinding Converter="{StaticResource StringFormatConverter}">
    <Binding Path="ResultValueControl.Min" FallbackValue=""/>
    <Binding Path="Format" />
</MultiBinding>

I also encountered this problem and found a solution in another post (https://stackoverflow.com/a/3139397/500099). The key is to use the FallbackValue="" property like this:

<MultiBinding Converter="{StaticResource StringFormatConverter}">
    <Binding Path="ResultValueControl.Min" FallbackValue=""/>
    <Binding Path="Format" />
</MultiBinding>
┾廆蒐ゝ 2024-12-03 02:55:33

我刚刚按照 Mr.Arcturus 的建议更改了 MainWindow.xaml,并且工作正常。

非常感谢Mr.Arcturus。

更改后就可以看到ManiWindow.xaml

<Window x:Class="DataPager.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        xmlns:Local="clr-namespace:DataPager.Convertor_For_BackGround">
    <Grid>
        <Grid.Resources>
            <Local:ButtonColorConverter x:Key="currentPageSetter"/>
        </Grid.Resources>
        <Grid.RowDefinitions>
            <RowDefinition Height="36*" />
            <RowDefinition Height="275*" />
        </Grid.RowDefinitions>
        <ItemsControl Name="pageControl" ItemsSource="{Binding Path=PageCollection}" Grid.Row="0">
            <ItemsControl.Template>
                <ControlTemplate TargetType="ItemsControl">
                    <Border >
                        <StackPanel>
                            <ItemsPresenter></ItemsPresenter>
                        </StackPanel>
                    </Border>
                </ControlTemplate>
            </ItemsControl.Template>
            <ItemsControl.ItemsPanel x:Uid="pageItemTemplate">
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button x:Name="pageNumberButton" Margin="3,4" Content="{Binding Path=Page_Number}">
                        <Button.Background>
                            <MultiBinding Converter="{StaticResource currentPageSetter}">
                                <Binding Path="Page_Number" />
                                **<Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}" Path="DataContext.CurrentPage.Page_Number" />** 
                            </MultiBinding>
                        </Button.Background>
                    </Button>
                </DataTemplate>
            </ItemsControl.ItemTemplate>

        </ItemsControl>
        <TextBox Text="{Binding Path=CurrentPage.Page_Number,Mode=TwoWay, FallbackValue=asdf}" Grid.Row="1" Height="23"  Margin="79,62,257,0" Name="textBox1" VerticalAlignment="Top" Width="167" />
        <Button Content="Button" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="121,110,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
    </Grid>
</Window>

I have just Changed in MainWindow.xaml as per Mr.Arcturus's suggestion and its working fine.

Thank you so much Mr.Arcturus.

you can see ManiWindow.xaml after chage

<Window x:Class="DataPager.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        xmlns:Local="clr-namespace:DataPager.Convertor_For_BackGround">
    <Grid>
        <Grid.Resources>
            <Local:ButtonColorConverter x:Key="currentPageSetter"/>
        </Grid.Resources>
        <Grid.RowDefinitions>
            <RowDefinition Height="36*" />
            <RowDefinition Height="275*" />
        </Grid.RowDefinitions>
        <ItemsControl Name="pageControl" ItemsSource="{Binding Path=PageCollection}" Grid.Row="0">
            <ItemsControl.Template>
                <ControlTemplate TargetType="ItemsControl">
                    <Border >
                        <StackPanel>
                            <ItemsPresenter></ItemsPresenter>
                        </StackPanel>
                    </Border>
                </ControlTemplate>
            </ItemsControl.Template>
            <ItemsControl.ItemsPanel x:Uid="pageItemTemplate">
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button x:Name="pageNumberButton" Margin="3,4" Content="{Binding Path=Page_Number}">
                        <Button.Background>
                            <MultiBinding Converter="{StaticResource currentPageSetter}">
                                <Binding Path="Page_Number" />
                                **<Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}" Path="DataContext.CurrentPage.Page_Number" />** 
                            </MultiBinding>
                        </Button.Background>
                    </Button>
                </DataTemplate>
            </ItemsControl.ItemTemplate>

        </ItemsControl>
        <TextBox Text="{Binding Path=CurrentPage.Page_Number,Mode=TwoWay, FallbackValue=asdf}" Grid.Row="1" Height="23"  Margin="79,62,257,0" Name="textBox1" VerticalAlignment="Top" Width="167" />
        <Button Content="Button" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="121,110,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
    </Grid>
</Window>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文