gpt4 book ai didi

c# - 具有 OneWayToSource 绑定(bind)的 SelectedIndex 不会触发

转载 作者:太空狗 更新时间:2023-10-29 17:52:05 26 4
gpt4 key购买 nike

我对特定的 xaml 数据绑定(bind)有疑问。我有两个列表框(主要细节,所以列表框将 IsSynchronizedWithCurrentItem 设置为 true)。我希望我的 View 模型知道详细信息列表框中的所选项目何时更改:我在我的 View 模型类上创建了一个 int 属性(即我们可以调用此属性 SelInd)并在详细信息 View 模型上以这种方式绑定(bind):

    SelectedIndex="{Binding Mode=OneWayToSource, Path=SelInd}"

我在运行时没有收到任何错误/异常,但绑定(bind)没有触发:当所选项目发生变化时,我的 View 模型的属性没有得到更新。如果我将绑定(bind)模式更改为 TwoWay 一切正常,但这不是我需要的。我需要它与 OneWayToSource 一起使用(顺便说一句,如果我将 SelectedItem 绑定(bind)到 SelectedValue 属性,同样的非工作行为适用)。

为什么这些绑定(bind)不使用 OneWayToSource 触发?

这里有一个更完整的代码示例,只是为了让事情更清楚:编辑:我无法展示真正的代码 (NDA),但我会在这里展示一些更简单和足够相似的东西(页面的 DataContext 是稍后解释的 PageViewModel 类的一个实例)我只需要我的 viewmodel 类的 SelInd 属性应该始终反射(reflect)第二个 ListBox 中 SelectedIndex 的值。我找到了执行此操作的替代方法(代码隐藏中的事件处理程序或附加行为)但现在我只是好奇为什么它不适用于 OneWayToSource 绑定(bind)。

<Page>
<ContentControl x:Name="MainDataContext">
<Grid DataContext={Binding Path=Masters}>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />

</Grid.ColumnDefinitions>

<ListBox Grid.Column="0"
SelectionMode="Single"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding }">
<ListBox.ItemContainerStyle>
...
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
....
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

<ListBox Grid.Column="1"
SelectionMode="Single"
SelectedIndex="{Binding Mode=OneWayToSource, ElementName=MainDataContext,Path=DataContext.SelInd}"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Path=Details}">
<ListBox.ItemContainerStyle>
...
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
....
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</ContentControl>
</Page>

这是 View 模型类的草图

public class PageViewModel{
public ObservableCollection<MasterClass> Masters {get;set;}

public int SelInd {get;set;}

....
}

这是 MasterClass,它只包含一个名称和一个详细信息列表

public class MasterClass{
public ObservableCollection<DetailsClass> Details {get;set;}

public String MasterName {get;set;}

....
}

最佳答案

我认为在您的情况下,您必须使用模式 OneWay。默认情况下,您已使用模式 TwoWay

引自 MSDN关于TwoWay:

TwoWay binding causes changes to either the source property or the target property to automatically update the other. This type of binding is appropriate for editable forms or other fully-interactive UI scenarios. Most properties default to OneWay binding, but some dependency properties (typically properties of user-editable controls such as the Text property of TextBox and the IsChecked property of CheckBox) default to TwoWay binding. A programmatic way to determine whether a dependency property binds one-way or two-way by default is to get the property metadata of the property using GetMetadata and then check the Boolean value of the BindsTwoWayByDefault property.

OneWay 模式,您需要:

OneWay binding causes changes to the source property to automatically update the target property, but changes to the target property are not propagated back to the source property. This type of binding is appropriate if the control being bound is implicitly read-only. For instance, you may bind to a source such as a stock ticker or perhaps your target property has no control interface provided for making changes, such as a data-bound background color of a table. If there is no need to monitor the changes of the target property, using the OneWay binding mode avoids the overhead of the TwoWay binding mode.

模式OneWayToSource:

OneWayToSource is the reverse of OneWay binding; it updates the source property when the target property changes. One example scenario is if you only need to re-evaluate the source value from the UI.

下图是为了更好地理解:

enter image description here

好的,那么我将向您展示一个适合我的示例。也许它会对你有用。

XAML

<Window x:Class="SelectedIndexHelp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SelectedIndexHelp"
Title="MainWindow" Height="350" Width="525"
ContentRendered="Window_ContentRendered"
WindowStartupLocation="CenterScreen">

<Window.Resources>
<local:SelectedIndexClass x:Key="SelectedIndexClass" />
</Window.Resources>

<Grid DataContext="{StaticResource SelectedIndexClass}">
<ListBox x:Name="MyListBox"
BorderThickness="1"
Width="200" Height="200"
BorderBrush="#CE5E48"
DisplayMemberPath="Name"
Background="AliceBlue"
SelectedIndex="{Binding MySelectedIndex, Mode=OneWayToSource}" />

<Label Name="SelectedIndex" VerticalAlignment="Top"
Content="{Binding MySelectedIndex}"
ContentStringFormat="SelectedIndex: {0}"
Width="100" Height="30" Background="Lavender" />
</Grid>
</Window>

代码隐藏

public partial class MainWindow : Window
{
public class Person
{
public string Name
{
get;
set;
}

public int Age
{
get;
set;
}
}

private ObservableCollection<Person> DataForListBox = new ObservableCollection<Person>();

public MainWindow()
{
InitializeComponent();
}

private void Window_ContentRendered(object sender, EventArgs e)
{
DataForListBox.Add(new Person()
{
Name = "Sam",
Age = 22,
});

DataForListBox.Add(new Person()
{
Name = "Nick",
Age = 21,
});

DataForListBox.Add(new Person()
{
Name = "Cris",
Age = 25,
});

DataForListBox.Add(new Person()
{
Name = "Josh",
Age = 36,
});

DataForListBox.Add(new Person()
{
Name = "Max",
Age = 32,
});

DataForListBox.Add(new Person()
{
Name = "John",
Age = 40,
});

MyListBox.ItemsSource = DataForListBox;
MyListBox.Focus();
}
}

public class SelectedIndexClass
{
private int? mySelectedIndex = 0;

public int? MySelectedIndex
{
get
{
return mySelectedIndex;
}

set
{
mySelectedIndex = value;
}
}
}

输出

enter image description here

在这个例子中,有一类数据——Person,这些数据为ListBox。和类 SelectedIndexClass (DataContext),它包含属性 MySelectedIndex,它是绑定(bind) OneWayToSource

编辑: 很高兴您能解决问题。我将尝试通过他们的例子来解释,你为什么不使用 ElementName 案例。

那么,假设我们有这段代码:

<ContentControl x:Name="MainDataContext">
<Grid x:Name="MainGrid" DataContext="{StaticResource SelectedIndexClass}">
<ListBox x:Name="MyListBox"
BorderThickness="1"
Width="200" Height="200"
BorderBrush="#CE5E48"
DisplayMemberPath="Name"
Background="AliceBlue"
SelectedIndex="{Binding Path=DataContext.MySelectedIndex, Mode=OneWayToSource, ElementName=MainDataContext}" />

<Label Name="SelectedIndex" VerticalAlignment="Top"
Content="{Binding MySelectedIndex}"
ContentStringFormat="SelectedIndex: {0}"
Width="100" Height="30" Background="Lavender" />
</Grid>
</ContentControl>

正如您可能理解的那样,它不会起作用。

DataContext 设置在可视化树的特定节点上,下面(在可视化树中)的所有项都继承它。这意味着 DataContextworkingGrid 和可视化树下方。因此,以下代码将起作用:

<ContentControl x:Name="MainDataContext">
<Grid x:Name="MainGrid" DataContext="{StaticResource SelectedIndexClass}">
<ListBox x:Name="MyListBox"
BorderThickness="1"
Width="200" Height="200"
BorderBrush="#CE5E48"
DisplayMemberPath="Name"
Background="AliceBlue"
SelectedIndex="{Binding Path=DataContext.MySelectedIndex, Mode=OneWayToSource, ElementName=MainGrid}" />

<Label Name="SelectedIndex" VerticalAlignment="Top"
Content="{Binding MySelectedIndex}"
ContentStringFormat="SelectedIndex: {0}"
Width="100" Height="30" Background="Lavender" />
</Grid>
</ContentControl>

此外,如果点的名称MyListBox,它将起作用。通常,在设置DataContext时,会传递元素名称。

关于c# - 具有 OneWayToSource 绑定(bind)的 SelectedIndex 不会触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18114605/

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