gpt4 book ai didi

c# - WPF 没有绑定(bind) ComboBox SelectedItem

转载 作者:太空狗 更新时间:2023-10-29 18:31:48 24 4
gpt4 key购买 nike

我已经进行了广泛的搜索,但找不到适合我的案例的任何解决方案。

我的项目中有几个组合框,我正在寻找一个自动完成解决方案,然后我找到了一个很好的解决方案并将其应用到我的项目中,我将解决方案的样式也应用到我项目中的所有组合框。

在那之后,SelectedItem 停止工作,有人可以帮助我吗?

我的组合框:

<ComboBox Name="CbOwnerType" Grid.Column="1" Grid.Row="2" ItemsSource="{Binding Path=OwnerTypes, Mode=OneWay}" SelectedItem="{Binding Owner.OwnerType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="Id" DisplayMemberPath="Name" Margin="5,0,10,0" />

我的风格:

<Style TargetType="{x:Type ComboBox}">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="FontWeight" Value="ExtraBold" />
<Setter Property="IsEditable" Value="False"/>
<Setter Property="IsSynchronizedWithCurrentItem" Value="False" />
<Setter Property="StaysOpenOnEdit" Value="True" />
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<ToggleButton Name="ToggleButton" Template="{StaticResource ComboBoxToggleButton}" Grid.Column="2" Focusable="True" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press" BorderThickness="0" />
<ContentPresenter Name="ContentSite" IsHitTestVisible="False" Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" Margin="5,0,20,0" VerticalAlignment="Center" HorizontalAlignment="Left" />
<TextBox x:Name="PART_EditableTextBox" Style="{x:Null}" Template="{StaticResource ComboBoxTextBox}" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="3,3,23,3" Focusable="True" Background="Transparent" Visibility="Hidden" IsReadOnly="{TemplateBinding IsReadOnly}" />
<Popup Name="Popup" Placement="Bottom" IsOpen="{TemplateBinding IsDropDownOpen}" AllowsTransparency="True" Focusable="False" PopupAnimation="Slide">
<Themes:SystemDropShadowChrome Margin="4,6,4,6" CornerRadius="4">
<Grid Name="DropDown" SnapsToDevicePixels="True" MinWidth="{TemplateBinding ActualWidth}" MaxHeight="{TemplateBinding MaxDropDownHeight}">
<Border x:Name="DropDownBorder" Background="{StaticResource WindowBackgroundBrush}" BorderThickness="1" BorderBrush="{StaticResource SolidBorderBrush}" />
<ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
<ItemsPresenter />
</ScrollViewer>
</Grid>
</Themes:SystemDropShadowChrome>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasItems" Value="false">
<Setter TargetName="DropDownBorder" Property="MinHeight" Value="95"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
<Trigger SourceName="Popup" Property="Popup.AllowsTransparency" Value="true">
<Setter TargetName="DropDownBorder" Property="CornerRadius" Value="4"/>
<Setter TargetName="DropDownBorder" Property="Margin" Value="0,2,0,0"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

更新

我的切换按钮

<ControlTemplate x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Border x:Name="Border" Grid.ColumnSpan="2" BorderBrush="{StaticResource LabPetsStandardColor}" BorderThickness="1" CornerRadius="5" />
<Border Grid.Column="0" Margin="1" Background="Transparent" BorderBrush="{StaticResource NormalBorderBrush}" BorderThickness="0" CornerRadius="5,0,0,5" />
<Path x:Name="Arrow" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" Data="M 0 0 L 4 4 L 8 0 Z">
<Path.Fill>
<SolidColorBrush Color="Black" />
</Path.Fill>
</Path>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsMouseOver" Value="true">
<Setter TargetName="Border" Property="Background" Value="{StaticResource LabPetsStandardColor}" />
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="true">
<Setter TargetName="Border" Property="Background" Value="{StaticResource LabPetsPressedStandardColor}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Border" Property="Background" Value="{StaticResource DisabledBackgroundBrush}" />
<Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource DisabledBorderBrush}" />
<Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
<Setter TargetName="Arrow" Property="Fill" Value="{StaticResource DisabledForegroundBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>

我的文本框

<Style x:Key="ComboBoxTextBox" TargetType="{x:Type TextBox}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="AllowDrop" Value="True" />
<Setter Property="MinWidth" Value="0" />
<Setter Property="MinHeight" Value="0" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" Background="#00FFFFFF" Name="PART_ContentHost" Focusable="False" VerticalAlignment="Center" VerticalContentAlignment="Center" Margin="0">
<ScrollViewer.Style>
<Style TargetType="ScrollViewer">
<Setter Property="OverridesDefaultStyle" Value="True" />
</Style>
</ScrollViewer.Style>
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

请问有人能帮帮我吗?

更新 2

找到了一个 hack,不是完美的解决方案,但有点工作......

如果我插入属性 SelectedValue 和值 Owner.OwnerTypeId,它就像一个魅力...但是,这是对的吗?

现在我的组合框:

<ComboBox Name="CbOwnerType" Grid.Column="1" Grid.Row="2" ItemsSource="{Binding Path=OwnerTypes, Mode=OneWay}" SelectedItem="{Binding Owner.OwnerType}" SelectedValue="{Binding Owner.OwnerTypeId}" SelectedValuePath="Id" DisplayMemberPath="Name" Margin="5,0,10,0" />

这是一个解决方案,不是我喜欢它,而是一个解决方案......有人可以回答为什么 SelectedItem 没有正常工作?

观察:当我更改选择时,SelectedItem 起作用,只是在我加载 View 时不起作用。

更新 3

好的,它像我说的那样工作,但问题是 WPF 在我的 ViewModel 上点击了 4 次,所以我稍微更改了我的 ComboBox:

<ComboBox Name="CbOwnerType" Grid.Column="1" Grid.Row="2" ItemsSource="{Binding Path=OwnerTypes, Mode=OneWay}" SelectedItem="{Binding Owner.OwnerType}" SelectedValue="{Binding Owner.OwnerTypeId, Mode=OneTime}" SelectedValuePath="Id" DisplayMemberPath="Name" Margin="5,0,10,0" />

现在,WPF 只需搜索 OwnerTypeId,当我更改项目时,WPF 只需点击 2 次。

更新 4

好吧,另一个奇怪的发现......在另一个具有相同属性(SelectedValue 除外)的 ComboBox 中,它运行完美...我不明白发生了什么。

更新 5

抱歉,我忘了发布我的模型。

模型所有者:

public class Owner
{
public int Id { get; set; }
public int OwnerTypeId { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string FormatedPhone
{
get
{
if (this.Phone == null)
return string.Empty;

switch (this.Phone.Length)
{
case 11:
return Regex.Replace(this.Phone, @"(\d{2})(\d{4})(\d{4})", "($1) $2-$3");
case 12:
return Regex.Replace(this.Phone, @"(\d{2})(\d{5})(\d{4})", "($1) $2-$3");
default:
return this.Phone;
}
}
}
public string Phone { get; set; }
public string CellPhone { get; set; }
public string FormatedCellPhone
{
get
{
if (this.CellPhone == null)
return string.Empty;

switch (this.CellPhone.Length)
{
case 11:
return Regex.Replace(this.Phone, @"(\d{2})(\d{4})(\d{4})", "($1) $2-$3");
case 12:
return Regex.Replace(this.Phone, @"(\d{2})(\d{5})(\d{4})", "($1) $2-$3");
default:
return this.CellPhone;
}
}
}
public string Email { get; set; }
public virtual OwnerType OwnerType { get; set; }
public virtual ICollection<Animal> Animals { get; set; }

public Owner()
{
this.OwnerType = new OwnerType();
this.Animals = new List<Animal>();

this.ErrorList = new StringBuilder();
}

模型所有者类型:

public class OwnerType
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Owner> Owners { get; set; }

public OwnerType()
{
this.Owners = new List<Owner>();
}
}

最佳答案

您的 SelectedItem 绑定(bind)不起作用,因为 WPF 通过 .Equals( ) 方法,默认情况下通过引用进行比较。内存中包含您的 SelectedItem 的实例与您的 ItemsSource

中的项目之一在内存中的实例不同

有 3 种方法可以处理这个问题。

  • 首先,正如您已经发现的那样,您可以将 SelectedValue 绑定(bind)到项目的值类型属性,并设置 SelectedValuePath

    <ComboBox ItemsSource="{Binding Path=OwnerTypes}" 
    SelectedValue="{Binding Owner.OwnerTypeId}"
    SelectedValuePath="Id" DisplayMemberPath="Name"
    />

    这通常是我采用的解决方案,因为它通常是最简单的

  • 其次,您可以确保将您的 SelectedItem 设置为内存中与 ItemsSource 项目之一相同的引用。根据应用程序设计,这也是一个不错的选择。

    public class Owner()
    {
    public int OwnerTypeId { get; set; }

    public OwnerType OwnerType
    {
    get
    {
    return StaticClass.OwnerTypes
    .FirstOrDefault(p => p.Id == this.OwnerTypeId);
    }

    set
    {
    if (value != null)
    OwnerTypeId = value.Id;
    }
    }
    }
  • 最后,您可以重写 OwnerType 对象上的 .Equals() 方法,因此如果 Id 属性相同。

    public override bool Equals(object obj) 
    {
    if (obj == null || !(obj is OwnerType))
    return false;

    return ((OwnerType)obj).Id == this.Id);
    }

    我通常尽量避免使用这种方法,除非我知道我总是只想通过 Id 属性来比较这个对象的相等性,但有时这是最好的方法。

    此外,无论何时覆盖 .Equals(),最好覆盖 .GetHashCode()

附带说明一下,您通常不希望同时绑定(bind) SelectedItemSelectedValue。它们是对同一事物进行设置的两种不同方式,将它们都绑定(bind)会得到意想不到的效果。

关于c# - WPF 没有绑定(bind) ComboBox SelectedItem,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20577321/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com