wpf combobox multibinding 无法在第一步中获取相对源组合框的组合框项目(以编程方式添加或绑定到数据库)
wpf combobox multibinding could not get combobox items (programmatically added or bind to database) of relative source combobox in first step
我想根据特定条件禁用某些组合框项目。对于这个问题,我使用了多重绑定。
如果我在xaml中描述了combobox的所有项目,就没有问题。但我想以编程方式填充组合框项目。所以在这种情况下,我无法获取项目,returns null,并在第一步中将我退出程序。
我的 xaml 代码是这样的:
<Window.Resources>
<local:TekerDisabler x:Key="tekerDisabler"/>
</Window.Resources>
<Grid>
<ComboBox x:Name="cbx" HorizontalAlignment="Left" Margin="41,125,0,0" VerticalAlignment="Top" Width="227">
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem">
<Setter Property="IsEnabled">
<Setter.Value>
<MultiBinding Converter="{StaticResource tekerDisabler}">
<Binding ElementName="txt1" Path="Text"/>
<Binding ElementName="txt2" Path="Text"/>
<Binding ElementName="txt3" Path="Text"/>
<Binding RelativeSource="{RelativeSource Self}"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
<TextBox x:Name="txt1" HorizontalAlignment="Left" Height="23" Margin="41,38,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
<TextBox x:Name="txt2" HorizontalAlignment="Left" Height="23" Margin="207,38,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="211" TextChanged="txt2_TextChanged"/>
<TextBox x:Name="txt3" HorizontalAlignment="Left" Height="24" Margin="478,37,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="196"/>
</Grid>
我的 C# 代码是这样的:
namespace App1.Pencereler
{
public partial class deneme : Window
{
public deneme()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
cbx.Items.Add("0");
cbx.Items.Add("1");
cbx.Items.Add("2");
cbx.Items.Add("3");
}
private void txt2_TextChanged(object sender, TextChangedEventArgs e)
{
cbx.SelectedIndex = 1;
}
}
class TekerDisabler : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
bool enable = true;
var itemler = values[3] as ComboBoxItem;
if (itemler == null || values[0].ToString() == null || values[1].ToString() == null || values[2].ToString() == null)
{ enable = true; }
else
{
switch (values[0].ToString())
{
case "a":
switch (values[1].ToString())
{
case "b":
switch (values[2].ToString())
{
case "c":
switch (itemler.Content.ToString())
{
case "0":
case "2":
enable = false;
break;
default:
enable = true;
break;
}
break;
default:
enable = true;
break;
}
break;
default:
enable = true;
break;
}
break;
default:
enable = true;
break;
}
}
return enable;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
例如,在第一步中,我写txt1:a、txt2:b、txt3:d等所有项目的显示启用,然后我写txt1:a, txt2:b, txt3:c 和combobox (0,2) 的内容禁用,没有问题。但是当 运行 程序时,在第一步我写 txt1:a, txt2:b, txt3:c 当下拉组合框时,程序把我赶出去了。
如何克服这个问题?
报错信息及详细信息如下:
错误详情如下:
System.NullReferenceException
HResult=0x80004003
İleti=Nesne başvurusu bir nesnenin örneğine ayarlanmadı.
Kaynak=App1
StackTrace:
konum App1.Pencereler.TekerDisabler.Convert(Object[] values, Type targetType, Object parameter, CultureInfo culture) D:\C Sharp\WPF\App1\App1\Pencereler\deneme.xaml.cs içinde: 60. satır
konum System.Windows.Data.MultiBindingExpression.TransferValue()
konum System.Windows.Data.MultiBindingExpression.Transfer()
konum System.Windows.Data.MultiBindingExpression.UpdateTarget(Boolean includeInnerBindings)
konum System.Windows.Data.MultiBindingExpression.AttachToContext(Boolean lastChance)
konum System.Windows.Data.MultiBindingExpression.AttachOverride(DependencyObject d, DependencyProperty dp)
konum System.Windows.Data.BindingExpressionBase.OnAttach(DependencyObject d, DependencyProperty dp)
如果知道您得到的确切错误是什么,那将很有趣。
我假设 ComboBoxItem.Content
returns null
。打开 ComboBox
后,将呈现(生成)项目容器。此时只有数据项存在。因此,第一次打开下拉列表时,所有项目容器 null
即将呈现。
无论如何,您的代码的以下简化版本很可能会解决您的问题:
TekerDisabler.cs
public class TekerDisabler : IMultiValueConverter
{
#region Implementation of IMultiValueConverter
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var currentItem = values[0] as string;
var predicate = "abc";
string input = string.Concat(values.Skip(1).Cast<string>());
return !(input.Equals(predicate, StringComparison.Ordinal)
&& (currentItem.Equals("0", StringComparison.Ordinal)
|| currentItem.Equals("2", StringComparison.Ordinal)));
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) =>
throw new NotSupportedException();
#endregion
}
TekerDisabler.cs - 替代版本
public class TekerDisabler : IMultiValueConverter
{
#region Implementation of IMultiValueConverter
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var currentItem = values[0] as string;
var predicate = "abc";
string input = string.Concat(values.Skip(1).Cast<string>());
return !(values[1].Equals("a", StringComparison.Ordinal)
&& values[2].Equals("b", StringComparison.Ordinal)
&& values[3].Equals("c", StringComparison.Ordinal)
&& (currentItem.Equals("0", StringComparison.Ordinal)
|| currentItem.Equals("2", StringComparison.Ordinal)));
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) =>
throw new NotSupportedException();
#endregion
}
MainWindow.xamlk.cs
partial class MainWIndow : Window
{
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register(
"Items",
typeof(ObservableCollection<string>),
typeof(MainWindow),
new PropertyMetadata(default(ObservableCollection<string>)));
public ObservableCollection<string> Items
{
get => (ObservableCollection<string>) GetValue(MainWindow.ResultsProperty);
set => SetValue(MainWindow.ResultsProperty, value);
}
}
MainWindow.xaml
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=main:MainWindow}, Path=Items}">
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem">
<Setter Property="IsEnabled">
<Setter.Value>
<MultiBinding Converter="{StaticResource CellForegroundMultiValueConverter}">
<Binding />
<Binding ElementName="TextBox1" Path="Text" />
<Binding ElementName="TextBox2" Path="Text" />
<Binding ElementName="TextBox3" Path="Text" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
<TextBox x:Name="TextBox1" />
<TextBox x:Name="TextBox2" />
<TextBox x:Name="TextBox3" />
我通过添加
成功解决了我的问题
cbx.IsDropDownOpen = true;
cbx.IsDropDownOpen = false;
在
之后
cbx.Items.Add("0");
cbx.Items.Add("1");
cbx.Items.Add("2");
cbx.Items.Add("3");
在 'Window_Loaded'
事件中。
我想根据特定条件禁用某些组合框项目。对于这个问题,我使用了多重绑定。 如果我在xaml中描述了combobox的所有项目,就没有问题。但我想以编程方式填充组合框项目。所以在这种情况下,我无法获取项目,returns null,并在第一步中将我退出程序。 我的 xaml 代码是这样的:
<Window.Resources>
<local:TekerDisabler x:Key="tekerDisabler"/>
</Window.Resources>
<Grid>
<ComboBox x:Name="cbx" HorizontalAlignment="Left" Margin="41,125,0,0" VerticalAlignment="Top" Width="227">
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem">
<Setter Property="IsEnabled">
<Setter.Value>
<MultiBinding Converter="{StaticResource tekerDisabler}">
<Binding ElementName="txt1" Path="Text"/>
<Binding ElementName="txt2" Path="Text"/>
<Binding ElementName="txt3" Path="Text"/>
<Binding RelativeSource="{RelativeSource Self}"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
<TextBox x:Name="txt1" HorizontalAlignment="Left" Height="23" Margin="41,38,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
<TextBox x:Name="txt2" HorizontalAlignment="Left" Height="23" Margin="207,38,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="211" TextChanged="txt2_TextChanged"/>
<TextBox x:Name="txt3" HorizontalAlignment="Left" Height="24" Margin="478,37,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="196"/>
</Grid>
我的 C# 代码是这样的:
namespace App1.Pencereler
{
public partial class deneme : Window
{
public deneme()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
cbx.Items.Add("0");
cbx.Items.Add("1");
cbx.Items.Add("2");
cbx.Items.Add("3");
}
private void txt2_TextChanged(object sender, TextChangedEventArgs e)
{
cbx.SelectedIndex = 1;
}
}
class TekerDisabler : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
bool enable = true;
var itemler = values[3] as ComboBoxItem;
if (itemler == null || values[0].ToString() == null || values[1].ToString() == null || values[2].ToString() == null)
{ enable = true; }
else
{
switch (values[0].ToString())
{
case "a":
switch (values[1].ToString())
{
case "b":
switch (values[2].ToString())
{
case "c":
switch (itemler.Content.ToString())
{
case "0":
case "2":
enable = false;
break;
default:
enable = true;
break;
}
break;
default:
enable = true;
break;
}
break;
default:
enable = true;
break;
}
break;
default:
enable = true;
break;
}
}
return enable;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
例如,在第一步中,我写txt1:a、txt2:b、txt3:d等所有项目的显示启用,然后我写txt1:a, txt2:b, txt3:c 和combobox (0,2) 的内容禁用,没有问题。但是当 运行 程序时,在第一步我写 txt1:a, txt2:b, txt3:c 当下拉组合框时,程序把我赶出去了。 如何克服这个问题?
报错信息及详细信息如下:
错误详情如下:
System.NullReferenceException
HResult=0x80004003
İleti=Nesne başvurusu bir nesnenin örneğine ayarlanmadı.
Kaynak=App1
StackTrace:
konum App1.Pencereler.TekerDisabler.Convert(Object[] values, Type targetType, Object parameter, CultureInfo culture) D:\C Sharp\WPF\App1\App1\Pencereler\deneme.xaml.cs içinde: 60. satır
konum System.Windows.Data.MultiBindingExpression.TransferValue()
konum System.Windows.Data.MultiBindingExpression.Transfer()
konum System.Windows.Data.MultiBindingExpression.UpdateTarget(Boolean includeInnerBindings)
konum System.Windows.Data.MultiBindingExpression.AttachToContext(Boolean lastChance)
konum System.Windows.Data.MultiBindingExpression.AttachOverride(DependencyObject d, DependencyProperty dp)
konum System.Windows.Data.BindingExpressionBase.OnAttach(DependencyObject d, DependencyProperty dp)
如果知道您得到的确切错误是什么,那将很有趣。
我假设 ComboBoxItem.Content
returns null
。打开 ComboBox
后,将呈现(生成)项目容器。此时只有数据项存在。因此,第一次打开下拉列表时,所有项目容器 null
即将呈现。
无论如何,您的代码的以下简化版本很可能会解决您的问题:
TekerDisabler.cs
public class TekerDisabler : IMultiValueConverter
{
#region Implementation of IMultiValueConverter
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var currentItem = values[0] as string;
var predicate = "abc";
string input = string.Concat(values.Skip(1).Cast<string>());
return !(input.Equals(predicate, StringComparison.Ordinal)
&& (currentItem.Equals("0", StringComparison.Ordinal)
|| currentItem.Equals("2", StringComparison.Ordinal)));
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) =>
throw new NotSupportedException();
#endregion
}
TekerDisabler.cs - 替代版本
public class TekerDisabler : IMultiValueConverter
{
#region Implementation of IMultiValueConverter
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var currentItem = values[0] as string;
var predicate = "abc";
string input = string.Concat(values.Skip(1).Cast<string>());
return !(values[1].Equals("a", StringComparison.Ordinal)
&& values[2].Equals("b", StringComparison.Ordinal)
&& values[3].Equals("c", StringComparison.Ordinal)
&& (currentItem.Equals("0", StringComparison.Ordinal)
|| currentItem.Equals("2", StringComparison.Ordinal)));
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) =>
throw new NotSupportedException();
#endregion
}
MainWindow.xamlk.cs
partial class MainWIndow : Window
{
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register(
"Items",
typeof(ObservableCollection<string>),
typeof(MainWindow),
new PropertyMetadata(default(ObservableCollection<string>)));
public ObservableCollection<string> Items
{
get => (ObservableCollection<string>) GetValue(MainWindow.ResultsProperty);
set => SetValue(MainWindow.ResultsProperty, value);
}
}
MainWindow.xaml
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=main:MainWindow}, Path=Items}">
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem">
<Setter Property="IsEnabled">
<Setter.Value>
<MultiBinding Converter="{StaticResource CellForegroundMultiValueConverter}">
<Binding />
<Binding ElementName="TextBox1" Path="Text" />
<Binding ElementName="TextBox2" Path="Text" />
<Binding ElementName="TextBox3" Path="Text" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
<TextBox x:Name="TextBox1" />
<TextBox x:Name="TextBox2" />
<TextBox x:Name="TextBox3" />
我通过添加
成功解决了我的问题 cbx.IsDropDownOpen = true;
cbx.IsDropDownOpen = false;
在
之后cbx.Items.Add("0");
cbx.Items.Add("1");
cbx.Items.Add("2");
cbx.Items.Add("3");
在 'Window_Loaded'
事件中。