我是C#新手,我不断收到以下无法删除的错误。
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''. BindingExpression:Path=HorizontalContentAlignment; DataItem=null; target element is 'RibbonGalleryItem' (Name=''); target property is 'HorizontalContentAlignment' (type 'HorizontalAlignment')
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''. BindingExpression:Path=VerticalContentAlignment; DataItem=null; target element is 'RibbonGalleryItem' (Name=''); target property is 'VerticalContentAlignment' (type 'VerticalAlignment')
我的代码如下,我不能确切地说出哪一行导致了错误,但我怀疑它与RibbonRadioButtons有关,因为如果我删除它们,我不会得到错误。只有在单击两个或更多单选按钮后,错误才会出现。ComboBoxItem上的一个回答继续抛出绑定错误,尽管style暗示是多个Refresh()语句导致了这个问题,但我不知道如何避免这个问题。
有人能帮我解决这个问题吗?
XAML
<Grid>
<DockPanel>
<r:Ribbon DockPanel.Dock="Top" x:Name="Ribbon" SelectedIndex="0">
<r:RibbonGroup Header="Continent" Width="Auto">
<r:RibbonComboBox x:Name="CountryList" Height="Auto" VerticalAlignment="Center" HorizontalContentAlignment="Left">
<r:RibbonGallery x:Name="cbSelectedCountry" SelectedValue="{Binding SelectedCountry, Mode=TwoWay}" SelectedValuePath="DisplayName" >
<r:RibbonGalleryCategory x:Name="cbCountryList" ItemsSource="{Binding CountryView}" DisplayMemberPath="DisplayName" />
</r:RibbonGallery>
</r:RibbonComboBox>
<WrapPanel>
<r:RibbonRadioButton x:Name="All" Label="All" GroupName="ContinentGroup"
Height="Auto" Width="Auto" HorizontalAlignment="Left"
IsChecked="{Binding Path=All}">
</r:RibbonRadioButton>
<r:RibbonRadioButton x:Name="Africa" Label="Africa" GroupName="ContinentGroup"
Height="Auto" Width="Auto" HorizontalAlignment="Left"
IsChecked="{Binding Path=Africa}">
</r:RibbonRadioButton>
<r:RibbonRadioButton x:Name="America" Label="America" GroupName="ContinentGroup"
Height="Auto" Width="Auto" HorizontalAlignment="Left"
IsChecked="{Binding Path=America}">
</r:RibbonRadioButton>
</WrapPanel>
</r:RibbonGroup>
</r:Ribbon>
</DockPanel>
</Grid>
C#
public class MySettings : INotifyPropertyChanged
{
private readonly ObservableCollection<Country> countries;
private ContinentViewModel selectedContinent;
private static string selectedCountry;
private int selectedRadioGroup;
private ObservableCollection<ContinentViewModel> continents;
private ListCollectionView countryView;
public event PropertyChangedEventHandler PropertyChanged;
private bool _All;
private bool _Africa;
private bool _America;
public MySettings()
{
countries = new ObservableCollection<Country>(
new[]
{
new Country() { Continent = Continent.Africa, DisplayName = "Algeria" },
new Country() { Continent = Continent.Africa, DisplayName = "Egypt" },
new Country() { Continent = Continent.Africa, DisplayName = "Chad" },
new Country() { Continent = Continent.Africa, DisplayName = "Ghana" },
new Country() { Continent = Continent.America, DisplayName = "Canada" },
new Country() { Continent = Continent.America, DisplayName = "Greenland" },
new Country() { Continent = Continent.America, DisplayName = "Haiti" }
});
CountryView = (ListCollectionView)CollectionViewSource.GetDefaultView(countries);
CountryView.Filter += CountryFilter;
Continents = new ObservableCollection<ContinentViewModel>(Enum.GetValues(typeof(Continent)).Cast<Continent>().Select(c => new ContinentViewModel { Model = c }));
}
public bool All
{
get => _All;
set
{
_All = value;
CountryView.Refresh();
SelectedCountry = _All ? countries.FirstOrDefault().DisplayName : SelectedCountry;
OnPropertyChanged("All");
}
}
public bool Africa
{
get => _Africa;
set
{
_Africa = value;
CountryView.Refresh();
SelectedCountry = _Africa ? countries.Where(_ => _.Continent == Continent.Africa).FirstOrDefault().DisplayName : SelectedCountry;
OnPropertyChanged("Africa");
}
}
public bool America
{
get => _America;
set
{
_America = value;
CountryView.Refresh();
SelectedCountry = _America ? countries.Where(_ => _.Continent == Continent.America).FirstOrDefault().DisplayName : SelectedCountry;
OnPropertyChanged("America");
}
}
private bool CountryFilter(object obj)
{
var country = obj as Country;
if (country == null) return false;
if (All && !Africa && !America) return true;
else if (!All && Africa && !America) return country.Continent == Continent.Africa;
else if (!All && !Africa && America) return country.Continent == Continent.America;
return true;
}
public ObservableCollection<ContinentViewModel> Continents
{
get => continents;
set
{
continents = value;
OnPropertyChanged("Continents");
}
}
public ListCollectionView CountryView
{
get => countryView;
set
{
countryView = value;
OnPropertyChanged("CountryView");
}
}
public class Country
{
public string DisplayName { get; set; }
public Continent Continent { get; set; }
}
public enum Continent
{
All,
Africa,
America
}
public class ContinentViewModel
{
public Continent Model { get; set; }
public string DisplayName => Enum.GetName(typeof(Continent), Model);
}
public ContinentViewModel SelectedContinent
{
get => selectedContinent;
set
{
selectedContinent = value;
OnContinentChanged();
this.OnPropertyChanged("SelectedContinent");
}
}
private void OnContinentChanged()
{
CountryView.Refresh();
}
public int SelectedRadioGroup
{
get => selectedRadioGroup;
set
{
selectedRadioGroup = value;
OnPropertyChanged("SelectedRadioGroup");
}
}
public string SelectedCountry
{
get => selectedCountry;
set
{
if (selectedCountry == value) return;
selectedCountry = value;
OnPropertyChanged("SelectedCountry");
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
我使用了 mvvmlight 并进行了一些更改以简化您的代码:
<Window x:Class="WpfTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfTest"
DataContext="{Binding Source={StaticResource Locator}, Path=Main}"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<DockPanel>
<Ribbon DockPanel.Dock="Top" x:Name="Ribbon" SelectedIndex="0">
<RibbonGroup Header="Continent" Width="Auto">
<RibbonComboBox x:Name="CountryList" Height="Auto" VerticalAlignment="Center" HorizontalContentAlignment="Left">
<RibbonGallery x:Name="cbSelectedCountry" SelectedItem="{Binding SelectedCountry, Mode=TwoWay}">
<RibbonGalleryCategory x:Name="cbCountryList" ItemsSource="{Binding CountryView}" DisplayMemberPath="DisplayName" />
</RibbonGallery>
</RibbonComboBox>
<WrapPanel>
<RibbonRadioButton x:Name="All" Label="All" GroupName="ContinentGroup" Height="Auto" Width="Auto" HorizontalAlignment="Left" IsChecked="{Binding Path=All}"></RibbonRadioButton>
<RibbonRadioButton x:Name="Africa" Label="Africa" GroupName="ContinentGroup" Height="Auto" Width="Auto" HorizontalAlignment="Left" IsChecked="{Binding Path=Africa}"></RibbonRadioButton>
<RibbonRadioButton x:Name="America" Label="America" GroupName="ContinentGroup" Height="Auto" Width="Auto" HorizontalAlignment="Left" IsChecked="{Binding Path=America}"></RibbonRadioButton>
</WrapPanel>
</RibbonGroup>
</Ribbon>
</DockPanel>
</Grid>
我创建了一个Country类型的属性SelectedCountry来绑定组合框,而不是像代码那样设置字符串。
using GalaSoft.MvvmLight;
using System.Collections.ObjectModel;
using System.Windows.Data;
namespace WpfTest.ViewModel
{
/// <summary>
/// This class contains properties that the main View can data bind to.
/// <para>
/// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
/// </para>
/// <para>
/// You can also use Blend to data bind with the tool's support.
/// </para>
/// <para>
/// See http://www.galasoft.ch/mvvm
/// </para>
/// </summary>
public class MainViewModel : ViewModelBase
{
private readonly ObservableCollection<Country> countries;
private ListCollectionView _countryView;
public ListCollectionView CountryView
{
get { return _countryView; }
set { this.Set(ref _countryView, value); }
}
private Country _SelectedCountry;
public Country SelectedCountry
{
get { return _SelectedCountry; }
set { this.Set(ref _SelectedCountry, value); }
}
private bool _All;
public bool All
{
get { return _All; }
set
{
this.Set(ref _All, value);
CountryView.Refresh();
}
}
private bool _Africa;
public bool Africa
{
get { return _Africa; }
set
{
this.Set(ref _Africa, value);
if (SelectedCountry != null && SelectedCountry.Continent != Continent.Africa)
{
SelectedCountry = null;
}
CountryView.Refresh();
}
}
private bool _America;
public bool America
{
get { return _America; }
set
{
this.Set(ref _America, value);
if (SelectedCountry != null && SelectedCountry.Continent != Continent.America)
{
SelectedCountry = null;
}
CountryView.Refresh();
}
}
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel()
{
countries = new ObservableCollection<Country>(
new[]
{
new Country() { Continent = Continent.Africa, DisplayName = "Algeria" },
new Country() { Continent = Continent.Africa, DisplayName = "Egypt" },
new Country() { Continent = Continent.Africa, DisplayName = "Chad" },
new Country() { Continent = Continent.Africa, DisplayName = "Ghana" },
new Country() { Continent = Continent.America, DisplayName = "Canada" },
new Country() { Continent = Continent.America, DisplayName = "Greenland" },
new Country() { Continent = Continent.America, DisplayName = "Haiti" }
});
CountryView = (ListCollectionView)CollectionViewSource.GetDefaultView(countries);
CountryView.Filter += CountryFilter;
CountryView.Refresh();
////if (IsInDesignMode)
////{
//// // Code runs in Blend --> create design time data.
////}
////else
////{
//// // Code runs "for real"
////}
}
private bool CountryFilter(object obj)
{
if (obj is Country c)
{
if (Africa && c.Continent != Continent.Africa)
{
return false;
}
if (America && c.Continent != Continent.America)
{
return false;
}
}
return true;
}
}
public enum Continent
{
All,
Africa,
America
}
public class Country
{
public string DisplayName { get; set; }
public Continent Continent { get; set; }
}
}
我没有得到您遇到的绑定错误,但我的数据上下文是从mvvmlight创建的定位器设置的。
如果您的代码在用户控件中使用,您可以通过获取网格并在用户控件中移动它(没有datacontext行)并让它从父数据文本派生来更改它。
我没有在.xaml中指定任何特殊的内容,所以我将省略该部分。除此之外,我希望能够使用Name属性设置SelectedItem。我非常希望答案在代码后面,但如果它愚蠢地复杂,只有xaml的答案也一样好。我没有MVVM的任何经验,我可以假设它会被建议。随着我对WPF的深入研究,我当然会扩展我在这方面的知识,但现在我只想让它发挥作用 这不是家庭作业 编辑:忘记列出我也会遇到的错误 系统.Windows。
使用Datagridtemplatecolumn将WPFDatagrid绑定到组合框。很难获得组合框绑定的selectedItem。我发现了类似的例子,但这并不能解决我的问题。 请在下面找到我的 XAML 的代码片段和数据结构: 我在上面定义了一个数据结构,它实现了INotifyPropertychanged接口。 现在,在视图模型中,有一个可观察的X列表集合,即XList,它绑定到XAML中的数
我有一个用户控件,其数据上下文设置为名为 EmployeeList_VM 的视图模型。然后,我在该用户控件中有一个 ContentControl,该控件将其 datacontect 设置为视图模型的公共属性 (EmployeeSelection)。ContentControl 的数据上下文与同一用户控件中列表框的选定项绑定相同。 我希望ContentControl中的combobox(属于名为Em
我有一个包含以下列的表格: 表在在线数据库中。我使用dataset.xsd文件和连接字符串在客户端和在线数据库之间进行通信。 以下是我使用的一些方法:
我在wpf c#应用程序中有一个组合框。在xaml中,我尝试执行以下操作。 ItemsSource 来自一个变量。选定项在另一个变量上设置值 但我希望显示的文本来自一个新变量。 如何停止使所选项目源显示为正文?
我有2个组合盒主从这样: 但当我在第一个组合框中选择一个项目时,它有空的“项目”列表,而我已经用“项目”选择了其中一个项目,并在第二个组合框选择了项目。第二个组合框中的文本不为空。我也尝试过使用IsSynchronizedWithCurrentItem=“False”。 是什么问题呢?