Проблема :
У меня есть пользовательское свойство зависимости (DP), называемое SelectedStoreString
, в пользовательском элементе управления, называемое StorePicker
. DP имеет PropertyChangedCallback
и CoerceValueCallback
. DP является двухсторонней привязкой к свойству в модели представления с тем же именем. Когда источнику присваивается значение в модели представления, вызывается CoerceValueCallback
, и он возвращает окончательное значение, которое должно быть передано между целевым DP и источником в модели представления (оно может совпадать с назначенным значением или другой, если он был изменен в обработчике).
Затем значение отправляется на PropertyChangedCallback
. Проблема в том, что приведенное значение, возвращаемое CoerceValueCallback
, никогда не распространяется на цель или источник. Я использую POCOViewModels Dev Express WPF Framework, поэтому интерфейс INotifyPropertyChanged
реализован в фоновом режиме.
Код :
//--------------------Poco view model--------------------------------------------------
[POCOViewModel]
public class FindOrdersViewModel
{
public virtual string SelectedStoreString { get; set; }
public FindOrdersViewModel()
{
SelectedStoreString = "48,49,55";
}
public static FindOrdersViewModel Create()
{
return ViewModelSource.Create(() => new FindOrdersViewModel());
}
}
//--------------------Dependency Property and its Handlers-----------------------------
public static DependencyProperty SelectedStoreStringProperty = DependencyProperty.Register(nameof(SelectedStoreString), typeof(string), typeof(StorePicker), new FrameworkPropertyMetadata("",
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
new PropertyChangedCallback(OnSelectedStoreStringChanged),
new CoerceValueCallback(CoerceSelectedStoreString),
false,
UpdateSourceTrigger.PropertyChanged));
public string SelectedStoreString
{
get
{
return (string) GetValue(SelectedStoreStringProperty); // _selectedStoreString;
}
set
{
SetValue(SelectedStoreStringProperty, value);
}
}
private static void OnSelectedStoreStringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
StorePicker storePicker = d as StorePicker;
if (d != null)
{
Dictionary<int, Store> sDct = new Dictionary<int, Store>();
foreach (Store store in _stores)
sDct.Add(store.STORE, store);
string value = e.NewValue as string;
if (value != null && value != "")
{
string[] strs = value.Split(',');
foreach (string s in strs)
{
try
{
int x = Convert.ToInt32(s);
Store outStore = sDct[x];
if (outStore != null)
{
if (!outStore.InActive)
{
storePicker.listBoxEdit1.SelectedItems.Add(outStore);
}
}
}
catch
{
}
}
}
}
}
private static object CoerceSelectedStoreString(DependencyObject d, object v)
{
StorePicker storePicker = d as StorePicker;
string finalSelectedStoresString = ""; //because the selectedstorestring may contain an Inactive store code we may need to adjust the string that was assigned
if (d != null)
{
string[] storeCodes = ((string)v) == "" ? new string[0]: ((string)v).Split(',');
foreach (string s in storeCodes)
{
Store temp = _stores.Find(x => x.STORE == Convert.ToInt32(s) && !x.InActive);
if (temp != null)
{
finalSelectedStoresString += temp.STORE + ",";
}
}
if (finalSelectedStoresString != "")
{
finalSelectedStoresString = finalSelectedStoresString.Remove(finalSelectedStoresString.Length - 1, 1); //remove the ending comma from the string if it has one
}
}
return finalSelectedStoresString;
}
//------------------------------How the control is used in xml---------------------------------------
<ctl:StorePicker x:Name="StorePicker" Grid.Row="2" Grid.Column="1" Margin="10,-4,0,4" StoreType="All" SelectedStoreString="{Binding SelectedStoreString,Mode=TwoWay}" IsAllStoresSelected="{Binding IsAllStoresSelected, Mode=TwoWay}"/>
Что я пробовал :
Вызов storePicker.SetCurrentValue (SelectedStoreStringProperty, e.NewValue as string)
из PropertyChangedCallback
. Это либо приводило к бесконечным l oop обратных вызовов, либо абсолютно ничего, если бы я использовал булеву переменную состояния, чтобы предотвратить бесконечное l oop. Но, тем не менее, не обновил привязку.
Установка режима привязки на Explicit и вызов storePicker.GetBindingExpression(SelectedStoreStringProperty).UpdateSource()
и storePicker.GetBindingExpression(SelectedStoreStringProperty).UpdateTarget()
для ручного обновления привязок. По-прежнему не обновлялись цель или источник.
Установка DP с помощью следующих методов (все из которых просто уничтожили привязку, тем самым победив цель): storePicker.SetValue(SelectedStoreStringProperty, e.NewValue as string), SelectedStoreString = e.NewValue as string
Что мне нужно :
Мне нужна возможность изменить значения свойства зависимости в выделенном фрагменте пользовательского элемента управления и передать эти значения в целевой DP и свойство источника в модели представления.