<RichTextBox x:Name="OrigText" Margin="0,0,8,0" d:LayoutOverrides="Width"/>
<Button x:Name="OrigFileBrowse" Command="{Binding BrowseCommand}" CommandParameter="{Binding ElementName=OrigText, Path=Document}" HorizontalAlignment="Center" Margin="0,0,8,2.442" Width="75" Content="Browse" Grid.Row="1" d:LayoutOverrides="Height"/>
<RichTextBox x:Name="ModifiedText" Grid.Column="1" Margin="8,0,0,0"/>
<Button x:Name="ModifiedFileBrowse" Command="{Binding BrowseCommand}" CommandParameter="{Binding ElementName=ModifiedText, Path=Document}" HorizontalAlignment="Center" Width="75" Content="Browse" Grid.Row="1" Grid.Column="1" Margin="0,0,0,2.442" d:LayoutOverrides="Height"/>
<Button x:Name="Compare" Command="{Binding CompareCommand}" HorizontalAlignment="Center" VerticalAlignment="Top" Width="75" Content="Compare" Grid.Row="2" Grid.ColumnSpan="2">
<Button.CommandParameter>
<x:Array Type="RichTextBox">
<local:CompareTextView/>
</x:Array>
</Button.CommandParameter>
</Button>
单击“比较”按钮时,尝试获取2个项目,然后执行比较命令。尝试使用MultiBinding但是在实例化时触发,因此转换器然后相应地触发。单击compare并执行compare命令时,它不会触发。
由于这不起作用,我现在尝试引用XAML中的控件以在ArrayExtension中传递。不确定语法或者是否可能,因为我知道你无法在ArrayExtension中绑定。上面的失败是因为它无法构造一个新的CompareTextView视图,因为我正在使用Prism ......所以没有默认的构造函数...
非常令人沮丧,希望有人可以帮助我...
修改
想清除一些事情。问题不在于我想再次调用CanExecute。问题在于,在实例化控件时,转换器被调用并执行并返回值......但是在他们去的地方我没有线索?永远不会再次调用转换器。如果我可以获得对FlowDocument的初始引用,这将是一个没有实际意义的点...但它本身并不返回任何东西...因为这是一个命令...如果这是有意义的...制作时使用MultiBinding。
<Button x:Name="Compare" Command="{Binding CompareCommand}" HorizontalAlignment="Center" VerticalAlignment="Top" Width="75" Content="Compare" Grid.Row="2" Grid.ColumnSpan="2">
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource FlowDocumentConverter}">
<Binding ElementName="OrigText" Path="Document"/>
<Binding ElementName="ModifiedText" Path="Document"/>
</MultiBinding>
</Button.CommandParameter>
</Button>
更新:
尝试了什么裁判提到here,向下滚动一下,看看他的帖子。虽然CanExecute不断触发,但这无法解决问题。另外我将MultiBinding切换为单个项目,它将返回null。再次当转换器在实例化时触发时,FlowDocument引用就在那里......
解答:
安倍提到它被缓存导致我尝试别的东西。因为我知道在调用转换器时FlowDocument引用是可用的,所以我知道它们在那里。有些东西被搞砸了。关键部分似乎在转换器本身。我只是返回对象[]。然后当命令触发时,arg确实是一个对象[]但是这两个项目都是null。我创建了一个名为Docs的类,它有两个属性,每个属性对应一个FlowDocument引用。当转换器触发时,我适当地设置了属性,然后返回Docs对象。现在当我启动compare命令时,Docs对象就是args,它就像我需要的那样引用了FlowDocuments!不确定这是否是设计的,但是在使用对象[]时项目丢失的事实对我来说没有意义。
答案 0 :(得分:2)
执行此操作的正确方法确实是MultiBinding
上的CommandParameter
。您不会看到它调用您的CanExecute
方法,除非WPF被告知该方法可以返回与已缓存的值不同的值(通过CanExecuteChanged
事件)。
由于您依赖传入的参数来确定这一点,因此我们必须在参数更改时引发事件。由于我们无法在命令中真正确定,我们可以使用另一种技术:告诉WPF在轮询UICommands
时随时轮询我们的命令。这是通过实施您的ICommand
来实现的:
public class MyCommand : ICommand
{
public void Execute(object parameter) { /* do stuff */ }
public bool CanExecute(object parameter { /* determine if we can do stuff */ }
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
显然,这会阻止您使用Prism DelegateCommand
,但这会响应命令参数的更改。
<强>更新强>
要考虑的另一件事是Document
上的RichTextBox
属性实际上并没有改变。相反,当您键入时,FlowDocument
的内容会发生变化。由于属性实例不会更改,因此转换器不会再次触发,并且最初转换的值将存储在CommandParameter
属性中。
强制转换器再次被调用的一种方法是向Binding
添加一个MultiBinding
,该RichTextBox
绑定到将每次更改的属性IsKeyboardFocusWithin
更改的文字。
一个有点hacky的解决方案是使用TextBox.Text
属性,因为它会模仿TextBox
的默认绑定行为(即当Binding
失去焦点时,{{1}更新):
<MultiBinding Converter="{StaticResource FlowDocumentConverter}">
<Binding ElementName="OrigText" Path="Document" />
<Binding ElementName="ModifiedText" Path="Document" />
<Binding ElementName="OrigText" Path="IsKeyboardFocusWithin" />
<Binding ElementName="ModifiedText" Path="IsKeyboardFocusWithin" />
</MultiBinding>
显然,在您的转换器中,您需要忽略这些附加值,因为它们与您的转换无关。