我开始意识到将所有这些音频文件打包到 xap 中只是一个坏主意,因为它现在已经增长到大约 60 mb。我不想再将我的音频文件与应用程序打包在一起,而是想使用 URL 并在用户按下声音按钮时将它们加载到独立存储中。我不确定如何使用我的应用程序执行此操作,因为我的按钮没有单独编码。它们会自动从 View 模型加载到 LongListSelectors 中。并根据单击哪个播放(data.filepath)。 下面,我尝试使用独立存储但收到错误。
更新的 mainpage.cs:
public partial class MainPage : PhoneApplicationPage
{
public string FilePath { get; set; }
WebClient _webClient;
// Constructor
public MainPage()
{
InitializeComponent();
// Set the data context of the listbox control to the sample data
DataContext = App.ViewModel;
//webclient download
_webClient = new WebClient();
_webClient.OpenReadCompleted += (s1, e1) =>
{
if (e1.Error == null)
{
try
{
string fileName = FilePath.
Substring(FilePath.LastIndexOf("/") + 1).Trim();
bool isSpaceAvailable =
IsSpaceIsAvailable(e1.Result.Length);
if (isSpaceAvailable)
{
// Save mp3 to Isolated Storage
using (var isfs = new IsolatedStorageFileStream(
fileName, FileMode.CreateNew,
IsolatedStorageFile.GetUserStoreForApplication()))
{
long fileLen = e1.Result.Length;
byte[] b = new byte[fileLen];
e1.Result.Read(b, 0, b.Length);
isfs.Write(b, 0, b.Length);
isfs.Flush();
}
}
else
{
MessageBox.Show("Not enough to save space available to download mp3.");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
else
{
MessageBox.Show(e1.Error.Message);
}
};
}
// Check to make sure there are enough space available on the phone
// in order to save the image that we are downloading on to the phone
private bool IsSpaceIsAvailable(long spaceReq)
{
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
long spaceAvail = store.AvailableFreeSpace;
if (spaceReq > spaceAvail)
{
return false;
}
return true;
}
}
// Sample code to localize the ApplicationBar
// Load data for the ViewModel Items
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (!App.ViewModel.IsDataLoaded)
{
App.ViewModel.LoadData();
}
}
private void LongListSelector_SelectionChanged(
object sender, SelectionChangedEventArgs e)
{
LongListSelector selector = sender as LongListSelector;
// verifying our sender is actually a LongListSelector
if (selector == null)
return;
SoundData data = selector.SelectedItem as SoundData;
// verifying our sender is actually SoundData
if (data == null)
return;
if (File.Exists(data.FilePath))
{
AudioPlayer.Source = new Uri(
data.FilePath,
UriKind.RelativeOrAbsolute);
}
else
{
using (var storageFolder =
IsolatedStorageFile.GetUserStoreForApplication())
{
using (var stream = new IsolatedStorageFileStream(
data.FilePath, FileMode.Open, storageFolder))
{
AudioPlayer.SetSource(stream);
}
}
}
selector.SelectedItem = null;
这是我的 SoundModel 模型的一部分。我留下了一个例子,说明它现在是如何使用本地存储进行设置的。另一个是 id 喜欢使用 url 的方式。
private SoundGroup CreateGamesGroup()
{
SoundGroup data = new SoundGroup();
data.Title = "Games";
string basePath = "assets/audio/Games/";
data.Items.Add(new SoundData
{
Title = "Gauntlet Exit",
FilePath = basePath + "GauntletExit.mp3",
Groups = "VideoGames"
});
data.Items.Add(new SoundData
{
Title = "Gauntlet Exit",
FilePath =
"http://k007.kiwi6.com/hotlink/23lenhzr3h/GauntletExit.mp3",
Groups="VideoGames"
});
由于 Mainpage.cs 引用了 SoundData 模型,因此我也将在此处添加:
public class SoundData : ViewModelBase
{
public string Title { get; set; }
public string FilePath { get; set; }
public string Items { get; set; }
public string Groups { get; set; }
public RelayCommand<string> SaveSoundAsRingtone { get; set; }
private void ExecuteSaveSoundAsRingtone(string soundPath)
{
App.Current.RootVisual.Dispatcher.BeginInvoke(() =>
{
SaveRingtoneTask task = new SaveRingtoneTask();
task.Source = new Uri("appdata:/" + this.FilePath);
task.DisplayName = this.Title;
task.Show();
}
);
}
public SoundData()
{
SaveSoundAsRingtone =
new RelayCommand<string>(ExecuteSaveSoundAsRingtone);
}
目前 url 无法正常工作,正如我预期的那样。我收到这些错误:
在 mscorlib.ni.dll 中发生类型为“System.IO.IsolatedStorage.IsolatedStorageException”的第一次机会异常 mscorlib.ni.dll 中出现“System.IO.IsolatedStorage.IsolatedStorageException”类型的异常,但未在用户代码中处理 附加信息:IsolatedStorageFileStream 上不允许的操作。
最佳答案
不确定这是否是您问题的根本原因,但您需要对 XAP 中包含的文件使用 appdata:/
,否则使用 isostore:/
当您通过暴露的属性将项目绑定(bind)到 LongListSelector 时,您可以将命令分配给您的项目并处理 View 模型中的“点击”。
假设您的 VM 中有以下内容:
public ObservableCollection<SoundData> AudioFiles { get; set; }
public ICommand PlayCommand { get; set; }
然后相关的 XAML 将类似于:
<phone:LongListSelector
x:Name="AudioFilesList"
ItemsSource="{Binding AudioFiles}"
SelectedItem="{Binding SoundData}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<command:EventToCommand
Command="{Binding PlayCommand}"
CommandParameter="{Binding Path=SelectedItem,
ElementName=AudioFilesList}"
PassEventArgsToCommand="False" />
</i:EventTrigger>
</i:Interaction.Triggers>
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<Grid>
<Border BorderThickness="2"
BorderBrush="{StaticResource PhoneForegroundBrush}"
Height="80">
<TextBlock
Text="{Binding FilePath}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Style="{StaticResource PhoneTextNormalStyle}" />
</Border>
</Grid>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
上面重要的部分是LongListSelector的ItemsSource、SelectedItem和PlayCommand的绑定(bind)。
我在@Git 上建立了一个小示例项目,希望它能帮助您解决问题https://github.com/mikkoviitala/any-ringtone
它通过 http 获取少量 mp3,将文件保存到 IsoStore,然后在 LongListSelector 中显示项目。点击列表项启动执行 Ringtonetask 的命令。
关于c# - 音频文件的独立存储不使用单独的点击事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24367081/