Рассмотрим приведенное ниже упрощенное приложение, которое позволяет выбирать между двумя элементами, каждый из которых имеет логические свойства A и B, привязанные к переключателям. Идея состоит в том, что вы должны иметь возможность устанавливать A/B независимо для каждого элемента, и если вы переключаетесь между элементами, радиокнопки должны отражать флаги для этого элемента. Однако это не так.RadioButton TwoWay Binding Issues
ViewModel:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Documents;
namespace SandboxWpf
{
public sealed class Element : INotifyPropertyChanged
{
private bool _memberA;
public bool MemberA
{
get { return _memberA; }
set
{
if (value != _memberA)
{
_memberA = value;
OnPropertyChanged();
}
}
}
private bool _memberB;
public bool MemberB
{
get { return _memberB; }
set
{
if (value != _memberB)
{
_memberB = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public sealed class MainViewModel : INotifyPropertyChanged
{
private readonly List<Element> _elements;
public MainViewModel()
{
_elements = new List<Element>();
_elements.Add(new Element());
_elements.Add(new Element());
}
public IEnumerable<Element> Elements
{
get { return _elements; }
}
private Element _selectedElement;
public Element SelectedElement
{
get { return _selectedElement; }
set
{
if (value != _selectedElement)
{
_selectedElement = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
окно XAML (не код позади):
<Window x:Class="SandboxWpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:SandboxWpf="clr-namespace:SandboxWpf"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<SandboxWpf:MainViewModel/>
</Window.DataContext>
<StackPanel Orientation="Horizontal">
<ListBox ItemsSource="{Binding Elements}"
SelectedItem="{Binding SelectedElement, Mode=TwoWay}" />
<ContentPresenter Content="{Binding SelectedElement}">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type SandboxWpf:Element}">
<StackPanel Orientation="Horizontal">
<RadioButton Content="A" IsChecked="{Binding MemberA, Mode=TwoWay}"/>
<RadioButton Content="B" IsChecked="{Binding MemberB, Mode=TwoWay}"/>
</StackPanel>
</DataTemplate>
</ContentPresenter.Resources>
</ContentPresenter>
</StackPanel>
</Window>
Вы можете переключить A и B значения с помощью переключателей на каждом элементе. Однако, если вы установите для первого элемента и второго элемента разные значения (один A и один B), затем вернитесь к другому выбранному элементу, а другой элемент теперь будет иметь как A, так и B значение false. Что-то неуловимое происходит, когда свойство SelectedElement изменяется на ContentPresenter, которое каким-то образом запускает привязку TwoWay, я думаю, заставляя ее перезаписывать значения свойств, но я не могу понять, почему это произойдет или как ее решить. Это преднамеренно упрощенная версия того, что я вижу в более крупном приложении.
Любая идея, что здесь происходит?
Это устраняет проблему, если я явно очистил другой флаг в моем обработчике для средства настройки свойств. Это немного неудобно; поведение по умолчанию сгруппированных радиокнопок, очищающих другие связанные флаги, выглядит любезно. В данном конкретном случае у него просто странное поведение (очистка каким-то образом применяется к устаревшей версии привязки, у которой еще нет сброса контекста данных)? –
Да, это немного неудобно, это больше делает сцену, использующую пользовательский элемент управления наследует togglebutton и перезаписывает свой стиль (выглядит как радиобуй, но не имеет групповой способности) –