Я не эксперт по bash, но этот работал для меня:
STR1="Hello"
STR2="World"
NEWSTR=$(cat << EOF
$STR1
$STR2
EOF
)
echo "$NEWSTR"
Мне было легче форматировать тексты.
Я наткнулся на подобную проблему и решил ее с помощью своего испытанного TriggerConverter.
public class TriggerConverter : IMultiValueConverter
{
#region IMultiValueConverter Members
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// First value is target value.
// All others are update triggers only.
if (values.Length < 1) return Binding.DoNothing;
return values[0];
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
Этот преобразователь значения берет любое количество параметров и пасует назад первого из них как преобразованное значение. При использовании в MultiBinding в случае он похож на следующее.
<ItemsControl
x:Name="commentsList"
ItemsSource="{Binding Path=SharedDataItemPM.Comments}"
Width="Auto" Height="Auto">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button
Content="Delete"
FontSize="10"
CommandParameter="{Binding}">
<Button.Command>
<MultiBinding Converter="{StaticResource TriggerConverter}">
<Binding Path="DataContext.DeleteCommentCommand"
ElementName="commentsList" />
<Binding />
</MultiBinding>
</Button.Command>
</Button>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
необходимо будет добавить TriggerConverter как ресурс где-нибудь, чтобы это работало. Теперь свойство Command установлено не, прежде чем значение для CommandParameter стало доступным. Вы могли даже связать с RelativeSource. Сам и CommandParameter вместо. достигнуть того же эффекта.
commandManager. InvalidateRequerySuggested работает на меня также. Я верю переговорам по следующей ссылке о подобной проблеме, и M$ dev подтвердил ограничение в текущей версии и commandManager. InvalidateRequerySuggested является обходным решением. http://social.expression.microsoft.com/Forums/en-US/wpf/thread/c45d2272-e8ba-4219-bb41-1e5eaed08a1f/
, Что важный синхронизация вызова commandManager. InvalidateRequerySuggested. Это должно быть вызвано после того, как соответствующее изменение значения уведомляется.
Съемка общим планом. для отладки этого, можно попробовать:
- проверка события PreviewCanExecute.
- используют snoop/wpf родинку, чтобы посмотреть внутри и видеть, каков commandparameter.
HTH,
Эй Jonas, не уверенный, если это будет работать в шаблоне данных, но здесь является обязательным синтаксисом, я использую в Контекстном меню ListView для захвата текущего объекта как параметра команды:
CommandParameter = "{Привязка RelativeSource = {RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget. SelectedItem, Mode=TwoWay}"
Вы можете использовать мой CommandParameterBehavior
, что я отправил на форумы Призмы вчера. Это добавляет недостающее поведение, где изменение в эти CommandParameter
заставляет Command
быть повторно запрошенным.
существует некоторая сложность, здесь вызванная моими попытками избежать утечки памяти, вызванной, если Вы звоните PropertyDescriptor.AddValueChanged
без более позднего вызова PropertyDescriptor.RemoveValueChanged
. Я пытаюсь зафиксировать это путем нерегистрации обработчика, когда элемент разгружен.
необходимо будет, вероятно, удалить эти IDelegateCommand
материал, если Вы не будете использовать Призму (и хотят внести те же изменения как я к библиотеке Prism). Также обратите внимание, что мы обычно не используем RoutedCommand
с здесь (мы используем Призму DelegateCommand<T>
для в значительной степени всего), поэтому не держите меня ответственный, если мой вызов к CommandManager.InvalidateRequerySuggested
выделяет своего рода квант wavefuntion каскад коллапса, который уничтожает известную вселенную или что-либо.
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
namespace Microsoft.Practices.Composite.Wpf.Commands
{
/// <summary>
/// This class provides an attached property that, when set to true, will cause changes to the element's CommandParameter to
/// trigger the CanExecute handler to be called on the Command.
/// </summary>
public static class CommandParameterBehavior
{
/// <summary>
/// Identifies the IsCommandRequeriedOnChange attached property
/// </summary>
/// <remarks>
/// When a control has the <see cref="IsCommandRequeriedOnChangeProperty" />
/// attached property set to true, then any change to it's
/// <see cref="System.Windows.Controls.Primitives.ButtonBase.CommandParameter" /> property will cause the state of
/// the command attached to it's <see cref="System.Windows.Controls.Primitives.ButtonBase.Command" /> property to
/// be reevaluated.
/// </remarks>
public static readonly DependencyProperty IsCommandRequeriedOnChangeProperty =
DependencyProperty.RegisterAttached("IsCommandRequeriedOnChange",
typeof(bool),
typeof(CommandParameterBehavior),
new UIPropertyMetadata(false, new PropertyChangedCallback(OnIsCommandRequeriedOnChangeChanged)));
/// <summary>
/// Gets the value for the <see cref="IsCommandRequeriedOnChangeProperty"/> attached property.
/// </summary>
/// <param name="target">The object to adapt.</param>
/// <returns>Whether the update on change behavior is enabled.</returns>
public static bool GetIsCommandRequeriedOnChange(DependencyObject target)
{
return (bool)target.GetValue(IsCommandRequeriedOnChangeProperty);
}
/// <summary>
/// Sets the <see cref="IsCommandRequeriedOnChangeProperty"/> attached property.
/// </summary>
/// <param name="target">The object to adapt. This is typically a <see cref="System.Windows.Controls.Primitives.ButtonBase" />,
/// <see cref="System.Windows.Controls.MenuItem" /> or <see cref="System.Windows.Documents.Hyperlink" /></param>
/// <param name="value">Whether the update behaviour should be enabled.</param>
public static void SetIsCommandRequeriedOnChange(DependencyObject target, bool value)
{
target.SetValue(IsCommandRequeriedOnChangeProperty, value);
}
private static void OnIsCommandRequeriedOnChangeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is ICommandSource))
return;
if (!(d is FrameworkElement || d is FrameworkContentElement))
return;
if ((bool)e.NewValue)
{
HookCommandParameterChanged(d);
}
else
{
UnhookCommandParameterChanged(d);
}
UpdateCommandState(d);
}
private static PropertyDescriptor GetCommandParameterPropertyDescriptor(object source)
{
return TypeDescriptor.GetProperties(source.GetType())["CommandParameter"];
}
private static void HookCommandParameterChanged(object source)
{
var propertyDescriptor = GetCommandParameterPropertyDescriptor(source);
propertyDescriptor.AddValueChanged(source, OnCommandParameterChanged);
// N.B. Using PropertyDescriptor.AddValueChanged will cause "source" to never be garbage collected,
// so we need to hook the Unloaded event and call RemoveValueChanged there.
HookUnloaded(source);
}
private static void UnhookCommandParameterChanged(object source)
{
var propertyDescriptor = GetCommandParameterPropertyDescriptor(source);
propertyDescriptor.RemoveValueChanged(source, OnCommandParameterChanged);
UnhookUnloaded(source);
}
private static void HookUnloaded(object source)
{
var fe = source as FrameworkElement;
if (fe != null)
{
fe.Unloaded += OnUnloaded;
}
var fce = source as FrameworkContentElement;
if (fce != null)
{
fce.Unloaded += OnUnloaded;
}
}
private static void UnhookUnloaded(object source)
{
var fe = source as FrameworkElement;
if (fe != null)
{
fe.Unloaded -= OnUnloaded;
}
var fce = source as FrameworkContentElement;
if (fce != null)
{
fce.Unloaded -= OnUnloaded;
}
}
static void OnUnloaded(object sender, RoutedEventArgs e)
{
UnhookCommandParameterChanged(sender);
}
static void OnCommandParameterChanged(object sender, EventArgs ea)
{
UpdateCommandState(sender);
}
private static void UpdateCommandState(object target)
{
var commandSource = target as ICommandSource;
if (commandSource == null)
return;
var rc = commandSource.Command as RoutedCommand;
if (rc != null)
{
CommandManager.InvalidateRequerySuggested();
}
var dc = commandSource.Command as IDelegateCommand;
if (dc != null)
{
dc.RaiseCanExecuteChanged();
}
}
}
}
Я нашел, что порядок, в котором я установил Команду и CommandParameter, имеет значение. Установка свойства Command заставляет CanExecute быть сразу названным, таким образом, Вы хотите, чтобы CommandParameter уже был установлен в той точке.
я нашел, что переключение порядка свойств в XAML может на самом деле иметь эффект, хотя я не уверен, что это решит Вашу проблему. Это стоит попытки, все же.
Вы, кажется, предполагаете, что кнопка никогда не становится включенной, что удивительно, так как я ожидал бы, что CommandParameter будет установлен вскоре после свойства Command в Вашем примере. Делает вызов CommandManager. InvalidateRequerySuggested () заставляют кнопку становиться включенной?
I've logged this as a bug against WPF in .Net 4.0, as the problem still exists in Beta 2.
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=504976
Существует относительно простой способ «исправить» эту проблему с помощью DelegateCommand, хотя он требует обновления исходного кода DelegateCommand и повторной компиляции Microsoft.Practices. Composite.Presentation.dll.
1) Загрузите исходный код Prism 1.2 и откройте CompositeApplicationLibrary_Desktop.sln. Здесь находится проект Composite.Presentation.Desktop, содержащий исходный код DelegateCommand.
2) В общедоступном событии EventHandler CanExecuteChanged измените его следующим образом:
public event EventHandler CanExecuteChanged
{
add
{
WeakEventHandlerManager.AddWeakReferenceHandler( ref _canExecuteChangedHandlers, value, 2 );
// add this line
CommandManager.RequerySuggested += value;
}
remove
{
WeakEventHandlerManager.RemoveWeakReferenceHandler( _canExecuteChangedHandlers, value );
// add this line
CommandManager.RequerySuggested -= value;
}
}
3) В защищенной виртуальной пустоте OnCanExecuteChanged () измените его следующим образом:
protected virtual void OnCanExecuteChanged()
{
// add this line
CommandManager.InvalidateRequerySuggested();
WeakEventHandlerManager.CallWeakReferenceHandlers( this, _canExecuteChangedHandlers );
}
4) Перекомпилируйте решение, затем перейдите к Папка отладки или выпуска, в которой находятся скомпилированные библиотеки DLL. Скопируйте Microsoft.Practices.Composite.Presentation.dll и .pdb (если хотите) туда, где вы ссылаетесь на свои внешние сборки, а затем перекомпилируйте приложение, чтобы получить новые версии.
После этого CanExecute должен запускаться каждый раз, когда пользовательский интерфейс отображает элементы, привязанные к рассматриваемой DelegateCommand.
Будь осторожен, Джо
, судья, Джо в Gmail