将UserControl值传递给View Page的ViewModel

时间:2016-04-13 08:22:26

标签: c# mvvm user-controls win-universal-app windows-10-universal

这是完整的Sample code
使用 MVVM 模式我的要求是将ListView置于其中

  1. 如果用户点击CheckBox上的ListView 故事板动画应该为True False播放,并且应该在数据库中更新ListView绑定值。如果为true,则勾选应弹出动画为false,勾选应该变为动画不可见。
    已解决根据@Elvis Xia回答
  2. 如果用户点击ListviewItem导航到值为
  3. 的新页面
  4. Blueprint
  5. 现在我使用了usercontrol创建datatemplate。在这里,我想分别用户点击checkbox或单独点击Item来识别这两个事件。
    使用ICommand我创建了两个代表,它们绑定到两个透明按钮继电器轻拍事件。在创建透明按钮和创建delgates时依赖于绑定它们让我觉得必须有更好的方法可以在没有任何代码的情况下利用 MVVM 来完成这些事件

    UserControl XAML

    <Button Background="LightBlue" BorderBrush="White" BorderThickness="4" Command="{x:Bind sampleItem.itemTapped}" CommandParameter="{Binding}" HorizontalContentAlignment="Stretch">
    
        <Grid Margin="20">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <TextBlock Margin="20" HorizontalAlignment="Center" Text="{x:Bind sampleItem.sampleText}" FontSize="30"/>
            <Image Grid.Column="1" Height="60" Width="60" Source="ms-appx:///Assets/check_off.png" HorizontalAlignment="Right"/>
            <Image x:Name="image" Grid.Column="1" Height="60" Width="60" Source="ms-appx:///Assets/check_on.png" HorizontalAlignment="Right"  Visibility="Collapsed" RenderTransformOrigin="0.5,0.5">
                <Image.RenderTransform>
                    <CompositeTransform/>
                </Image.RenderTransform>
            </Image>
            <Button x:Name="btnFav" Grid.Column="1"  Height="60" Width="60" HorizontalAlignment="Right" Background="Transparent" Command="{x:Bind sampleItem.favTapped}" CommandParameter="{Binding}">
                <Interactivity:Interaction.Behaviors>
                    <!--<Core:EventTriggerBehavior EventName="Tapped">
                    <Core:InvokeCommandAction Command="{Binding favTapped}" />
                </Core:EventTriggerBehavior>-->
                    <Core:DataTriggerBehavior Binding="{Binding isFav}" Value="true">
                        <Media:ControlStoryboardAction Storyboard="{StaticResource StoryboardCheckOn}"/>
                    </Core:DataTriggerBehavior>
                    <Core:DataTriggerBehavior Binding="{Binding isFav}" Value="false">
                        <Media:ControlStoryboardAction Storyboard="{StaticResource StoryboardCheckOff}"/>
                    </Core:DataTriggerBehavior>
                </Interactivity:Interaction.Behaviors>
            </Button>
        </Grid>
    </Button>
    

    UserControl XAML codeBehind

    MainPageModel sampleItem { get { return this.DataContext as MainPageModel; } }
            public MainPageUserControl()
            {
                this.InitializeComponent();
                this.DataContextChanged += (s, e) => this.Bindings.Update();
            }
    

    Viewmodel代码

    public async Task GetData()
    {
        for (int i = 0; i < 10; i++)
        {
            if (i == 3)
                sampleList.Add(new MainPageModel { sampleText = "Selected", isFav = true, favTapped= new DelegateCommand<MainPageModel>(this.OnFavTapped), itemTapped= new DelegateCommand<MainPageModel>(this.OnItemTapped)});
            else
                sampleList.Add(new MainPageModel { sampleText = "UnSelected"+i.ToString(), isFav = null, favTapped = new DelegateCommand<MainPageModel>(this.OnFavTapped), itemTapped = new DelegateCommand<MainPageModel>(this.OnItemTapped) });
    }
    }
    private void OnFavTapped(MainPageModel arg)
    {
        if (arg.isFav == null) arg.isFav = true;
        else
            arg.isFav = !arg.isFav;
    }
    private void OnItemTapped(MainPageModel arg)
    {
        System.Diagnostics.Debug.WriteLine("Button Value: "+arg.sampleText);
        System.Diagnostics.Debug.WriteLine("Selected Item Value: "+selectedItem.sampleText);
    }
    

    MainPage Xaml

     <Grid Grid.Row="1">
                <ListView  ItemsSource="{x:Bind ViewModel.sampleList}" IsItemClickEnabled="True" SelectedItem="{Binding ViewModel.selectedItem,Mode=TwoWay}">
                    <ListView.ItemTemplate>
                        <DataTemplate>                       
                                <userControls:MainPageUserControl/>                       
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </Grid>
    

    使用背后的代码必须有更好的方法来实现所需的结果。

2 个答案:

答案 0 :(得分:1)

项目中每个项目的DataContext都是MainPageModel类的实例。所以favTapped命令应该添加到MainPageModel类。它是一个命令,所以favTapped应该是一个新类的实例,它实现ICommand接口。

如果您不想在首次加载页面时显示动画,则可以将isFav设置为bool?。当页面首次加载时,将isFav的值设置为null,从而不会触发动画操作。

以下是代码段和演示链接:

ViewModelCommands.cs:

public class ViewModelCommands : ICommand
{
    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        //if it's a tapped event
        if (parameter is TappedRoutedEventArgs)
        {
            var tappedEvent = (TappedRoutedEventArgs)parameter;
            var gridSource = (Grid)tappedEvent.OriginalSource;
            var dataContext = (MainPageModel)gridSource.DataContext;
            //if tick is true then set to false, or the opposite.
            if (dataContext.isFav == null)
            {
                dataContext.isFav = true;
            } else
            {
                dataContext.isFav = !dataContext.isFav;
            }
        }
    }
}

MainPageModel.cs:

 public class MainPageModel:BindableBase
{

    public MainPageModel() {
        favTapped = new ViewModelCommands();
    }
    public ViewModelCommands favTapped { get; set; }
    private string _sampleText;
    public string sampleText
    {
        get
        {
            return this._sampleText;
        }
        set
        {
            Set(ref _sampleText, value);
        }
    }
    private bool? _isFav;
    public bool? isFav
    {
        get
        {
            return this._isFav;
        }
        set
        {
            Set(ref _isFav, value);
        }
    }
}

以下是完整的演示:Demo Project

<强>更新

使用DelegateCommand时,可以将命令Property添加到MainPageModel.cs,因为项目的DataContext是MainPageModel实例。您可以使用this.isFav更改点击项目的isFav值。

以下是MainPageModel.cs的代码:

public class MainPageModel : BindableBase
{
    private DelegateCommand _favTapped;

    public DelegateCommand favTapped
    {
        get
        {
            if (_favTapped == null)
            {
                _favTapped = new DelegateCommand(() =>
                {
                    //Here implements the check on or off logic
                    this.CheckOnOff();
                }, () => true);
            }
            return _favTapped;
        }
        set { _favTapped = value; }
    }

    private void CheckOnOff()
    {
        if (this.isFav == null)
        {
            this.isFav = true;
        }
        else
        {
            this.isFav = !this.isFav;
        }
    }
    private string _sampleText;
    public string sampleText
    {
        get
        {
            return this._sampleText;
        }
        set
        {
            Set(ref _sampleText, value);
        }
    }
    private bool? _isFav;
    public bool? isFav
    {
        get
        {
            return this._isFav;
        }
        set
        {
            Set(ref _isFav, value);
        }
    }
}
  

对于Listview项目选择

您可以使用ListView.ItemClick事件。但你也应该设置IsItemClickEnabled =&#34; True&#34;否则事件处理程序不会被解雇。

  

对于Listview的子项目点击

您可以使用userControl的Tapped Event。

以下是Xaml代码,显示了如何注册以上两个事件:

<Grid Grid.Row="1">
    <ListView IsItemClickEnabled="True" ItemClick="ListView_ItemClick_1" ItemsSource="{x:Bind ViewModel.sampleList}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <userControls:MainPageUserControl  Tapped="MainPageUserControl_Tapped"/>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

答案 1 :(得分:1)

public class ViewMOdel()
{ 
       public ViewModel()
    {
favTapped= new DelegateCommand<MainPageModel>(this.OnFavTapped)
 itemTapped= new DelegateCommand<MainPageModel>(this.OnItemTapped)
    }

public async Task GetData()
    {
        for (int i = 0; i < 10; i++)
        {
            if (i == 3)
                sampleList.Add(new MainPageModel { sampleText = "Selected", isFav = true});
            else
                sampleList.Add(new MainPageModel { sampleText = "UnSelected"+i.ToString(), isFav = null});
    }
    }
    private void OnFavTapped(MainPageModel arg)
    {
        if (arg.isFav == null) arg.isFav = true;
        else
            arg.isFav = !arg.isFav;
    }
    private void OnItemTapped(MainPageModel arg)
    {
        System.Diagnostics.Debug.WriteLine("Button Value: "+arg.sampleText);
        System.Diagnostics.Debug.WriteLine("Selected Item Value: "+selectedItem.sampleText);
    }
    }

绑定应该是这样的

<Button x:Name="btnFav" Grid.Column="1"  Height="60" Width="60" HorizontalAlignment="Right" Background="Transparent" Command="{Binding ElementName=UserControl, Path=Tag.favTapped}" CommandParameter="{Binding}"/>

<强>更新

<ListView  ItemsSource="{x:Bind ViewModel.sampleList}"  x:Name="Listview"IsItemClickEnabled="True" SelectedItem="{Binding ViewModel.selectedItem,Mode=TwoWay}">
                    <ListView.ItemTemplate>
                        <DataTemplate>                       
                                <userControls:MainPageUserControl Tag="{Binding DataContext,ElementName=Listview}"/>                       
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
 <Button x:Name="btnFav" Grid.Column="1"  Height="60" Width="60" HorizontalAlignment="Right" Background="Transparent" Command="{Binding ElementName=UserControl, Path=Tag.favTapped}" CommandParameter="{Binding}"/>
使用EventTriggerBehavior

Update2

 favTapped = new DelegateCommand<RoutedEventArgs>(this.OnFavTapped);

private void OnFavTapped(RoutedEventArgs arg)
        {
         var item =  (( arg.OriginalSource )as Button).DataContext as MainPageModel
        }

<Button n x:Name="btnFav" Grid.Column="1"  Height="60" Width="60" HorizontalAlignment="Right" Background="Transparent"   >
            <interact:Interaction.Behaviors>

                <interactcore:EventTriggerBehavior EventName="Click" >
                    <interactcore:InvokeCommandAction Command="{Binding ElementName=usercontrol, Path=Tag.favTapped}" />
                </interactcore:EventTriggerBehavior>
            </interact:Interaction.Behaviors>
        </Button>